বাশ শেল আপনাকে পাটিগণিত ওভারফ্লো ইত্যাদি সম্পর্কে সতর্ক না করার যুক্তি কী?


9

bashশেলের পাটিগণিত মূল্যায়ন ক্ষমতাগুলির জন্য সীমাবদ্ধতা রয়েছে । ম্যানুয়ালটি শেল পাটিগণিতের এই দিকটি সম্পর্কে সামঞ্জস্যপূর্ণ তবে বলা হয়েছে :

অতিরিক্ত প্রবাহের জন্য কোনও পরীক্ষা ছাড়াই স্থির-প্রস্থের পূর্ণসংখ্যায় মূল্যায়ন করা হয়, যদিও 0 দ্বারা বিভাজন আটকে যায় এবং ত্রুটি হিসাবে চিহ্নিত করা হয়। অপারেটর এবং তাদের নজির, সাহচর্য এবং মানগুলি সি ভাষার মতো in

স্থায়ী-প্রস্থের কোনটি পূর্ণসংখ্যা এই বোঝায় সত্যিই যা সম্পর্কে হয় ডাটা টাইপ ব্যবহার করা হয় (এবং কেন এই এই বহির্ভূত সুনির্দিষ্ট) কিন্তু সীমা মান প্রকাশ করা হয় /usr/include/limits.hএই ফ্যাশন:

#  if __WORDSIZE == 64
#   define ULONG_MAX     18446744073709551615UL
#  ifdef __USE_ISOC99
#  define LLONG_MAX       9223372036854775807LL
#  define ULLONG_MAX    18446744073709551615ULL

এবং একবার আপনি এটি জানেন, আপনি এই মত সত্য এই অবস্থা নিশ্চিত করতে পারেন:

# getconf -a | grep 'long'
LONG_BIT                           64
ULONG_MAX                          18446744073709551615

এটি একটি 64 বিট পূর্ণসংখ্যা এবং এটি পাটিগণিত মূল্যায়নের প্রসঙ্গে শেলের মধ্যে সরাসরি অনুবাদ করে:

# echo $(((2**63)-1)); echo $((2**63)); echo $(((2**63)+1)); echo $((2**64))
9223372036854775807        //the practical usable limit for your everyday use
-9223372036854775808       //you're that much "away" from 2^64
-9223372036854775807     
0
# echo $((9223372036854775808+9223372036854775807))
-1

সুতরাং 2 এর মধ্যে 63 2 এবং 64 -1, আপনি নেতিবাচক পূর্ণসংখ্যার আপনি কতদূর ULONG_MAX থেকে মুছে তুমি দেখাচ্ছে পেতে 1 । মূল্যায়ন যখন এই সীমাতে পৌঁছে যায় এবং প্রবাহিত হয়, যাই হোক না কেন আদেশ অনুসারে, আপনি কোনও সতর্কতা পান না এবং মূল্যায়নের সেই অংশটি 0 এ পুনরায় সেট করা হয় যা ডান-অ্যাসোসিয়েটিভ এক্সপেনসিটির মতো উদাহরণ সহ কিছু অস্বাভাবিক আচরণ করতে পারে :

echo $((6**6**6))                      0   // 6^46656 overflows to 0
echo $((6**6**6**6))                   1   // 6^(6^46656) = 6^0 = 1
echo $((6**6**6**6**6))                6   // 6^(6(6^46656)) = 6^(6^0) = 6^1
echo $((6**6**6**6**6**6))         46656   // 6^(6^(6^(6^46656))) = 6^6
echo $((6**6**6**6**6**6**6))          0   // = 6^6^6^1 = 0
...

ব্যবহারের sh -c 'command'ফলে কোনও পরিবর্তন হয় না তাই আমাকে ধরে নিতে হবে এটি স্বাভাবিক এবং কমপ্লায়েন্ট আউটপুট। এখন যেহেতু আমি মনে করি পাটিগণিতের সীমা এবং সীমা এবং এক্সপ্রেশন মূল্যায়নের জন্য শেলের মধ্যে এটির আমার কাছে একটি মৌলিক তবে কংক্রিট বোঝাপড়া আছে, আমি ভেবেছিলাম যে লিনাক্সের অন্যান্য সফ্টওয়্যারগুলি কী কী ডেটা ব্যবহার করে তা আমি খুব শীঘ্রই উঁকি দিতে পারি। bashএই কমান্ডটির ইনপুট পরিপূরক করতে আমি কিছু উত্স ব্যবহার করেছি:

{ shopt -s globstar; for i in /path/to/source_bash-4.2/include/**/*.h /usr/include/**/*.h; do grep -HE '\b(([UL])|(UL)|())LONG|\bFLOAT|\bDOUBLE|\bINT' $i; done; } | grep -iE 'bash.*max'

bash-4.2/include/typemax.h:#    define LLONG_MAX   TYPE_MAXIMUM(long long int)
bash-4.2/include/typemax.h:#    define ULLONG_MAX  TYPE_MAXIMUM(unsigned long long int)
bash-4.2/include/typemax.h:#    define INT_MAX     TYPE_MAXIMUM(int)

ifবিবৃতিগুলির সাথে আরও আউটপুট রয়েছে এবং আমি awkখুব কম ইত্যাদির মতো কমান্ডও সন্ধান করতে পারি I আমি যে নিয়মিত অভিব্যক্তিটি ব্যবহার করেছি তা লক্ষ্য করেছিলাম যেমন আমার bcএবং সুনির্দিষ্ট যথাযথ সরঞ্জামগুলি সম্পর্কে কিছুই ধরা পড়ে না dc


প্রশ্নাবলি

  1. awkযখন আপনার গাণিতিক মূল্যায়ন উপচে পড়েছে তখন আপনাকে সতর্ক না করার যুক্তি (যেমন 2 ^ 1024 মূল্যায়ন করার সময় কী করে)? কেন 2 এর মধ্যে নেতিবাচক পূর্ণসংখ্যা 63 এবং 2 64 -1 শেষ ব্যবহারকারীর যখন তিনি কিছু মূল্যায়নের এর উন্মুক্ত?
  2. আমি কোথাও পড়েছি যে ইউনিক্সের কিছু স্বাদ ইন্টারেক্টিভভাবে ইউলং_ম্যাক্স পরিবর্তন করতে পারে? কেউ কি এই ব্যাপারে শুনেছে?
  3. যদি কেউ নির্বিচারে স্বাক্ষরযুক্ত পূর্ণসংখ্যার মান সর্বাধিক পরিবর্তিত করে limits.h, তবে পুনরুদ্ধার করে bash, আমরা কী আশা করতে পারি?

বিঃদ্রঃ

1. আমি যা দেখেছি তা আরও স্পষ্টভাবে চিত্রিত করতে চেয়েছিলাম, কারণ এটি খুব সাধারণ অভিজ্ঞতামূলক জিনিস। আমি যা লক্ষ্য করেছি তা হ'ল:

  • (ক) যে কোনও মূল্যায়ন <2 ^ 63-1 দেয় তা সঠিক
  • (খ) যে কোনও মূল্যায়ন যা => 2 ^ 63 কে 2 ^ 64 পর্যন্ত দেয় তা aণাত্মক পূর্ণসংখ্যা দেয়:
    • সেই পূর্ণসংখ্যার ব্যাপ্তি x থেকে y পর্যন্ত। x = -9223372036854775808 এবং y = 0।

এটি বিবেচনা করে, (খ) এর মতো মূল্যায়ন 2 ^ 63-1 এর সাথে x_y এর মধ্যে কিছু হিসাবে প্রকাশ করা যেতে পারে। উদাহরণস্বরূপ যদি আমরা আক্ষরিকভাবে (2 ^ 63-1) +100 002 মূল্যায়ন করতে বলা হয় (তবে এর চেয়ে কম সংখ্যক (ক) হতে পারে) আমরা পেয়ে যাব -9223372036854675807। আমি যে স্পষ্টভাবে অনুমান করছি তা কেবল উল্লেখ করছি তবে এর অর্থ এটিও যে নিম্নলিখিত দুটি প্রকাশ:

  • (2 ^ 63-1) + 100 002 এবং;
  • (2 ^ 63-1) + (এলএলং_ম্যাক্স - the শেলটি আমাদের জন্য কী দেয় ((2 ^ 63-1) + 100 002), যা আমাদের -9 ইতিবাচক মানগুলি ব্যবহার করে ভাল করে;
    • (2 ^ 63-1) + (9223372036854775807 - 9223372036854675807 = 100 000)
    • = 9223372036854775807 + 100 000

সত্যিই খুব কাছাকাছি। দ্বিতীয় এক্সপ্রেশনটি "2" (2 ^ 63-1) + 100 002 বাদে যা আমরা মূল্যায়ন করছি। আমি বলতে চাইছি এটিই আপনি নেতিবাচক পূর্ণসংখ্যাগুলি দেখায় যে আপনি 2 ^ 64 থেকে কত দূরে আছেন showing আমি সেই নেতিবাচক পূর্ণসংখ্যার এবং সীমাগুলির জ্ঞানের সাথে বোঝাতে চাইছি আপনি ভাল শ্যাশের x..y রেঞ্জের মধ্যে মূল্যায়ন শেষ করতে পারবেন না তবে আপনি অন্য কোথাও করতে পারেন - সেই অর্থে ডেটা 2 ^ 64 অবধি ব্যবহারযোগ্য হয় (আমি যুক্ত করতে পারতাম এটি কাগজে আপ করুন বা এটি বিসি ব্যবহার করুন)। এর বাইরে যাইহোক আচরণটি 6 ^ 6 ^ 6 এর সমান, কারণ সীমাতে বর্ণিত সীমাটি সীমাতে পৌঁছেছে বলে ...


5
আমার ধারণা হ'ল যৌক্তিকতাটি "শেল গণিতের জন্য সঠিক সরঞ্জাম নয়" এ ফুটে উঠেছে। এটি এর জন্য ডিজাইন করা হয়নি এবং আপনি যেমন দেখান তেমন মনোযোগ দিয়ে এটি মোকাবেলার চেষ্টা করে না। জাহান্নাম, বেশিরভাগ শাঁস এমনকি ভেসে উঠতে পারে না!
টেরডন

@ ইটারডন যদিও শেলটি এই ক্ষেত্রে সংখ্যার সাথে যেভাবে আচরণ করে তা হ'ল আমি কখনও শুনেছি এমন প্রতিটি উচ্চ স্তরের ভাষার মতোই। পূর্ণসংখ্যার প্রকারগুলি একটি নির্দিষ্ট আকার এবং প্রবাহিত হতে পারে।
স্বর্ণিলোক

@ আটারডন প্রকৃতপক্ষে, 6 ^ 6 ^ 6 টাইমিং কিউআই এটি অনুধাবন করার পরে আমি এটি নিয়ে গবেষণা করেছি। আমি বেশি কন্টেন্ট খুঁজে না পাবার কারণটিও অনুমান করেছিলাম কারণ এটি সি, বা এমনকি সি 99 এর সাথে করার ছিল। যেহেতু আমি কোনও বিকাশকারী বা আইটি ব্যক্তি নই, তাই সমস্ত ধারণার সাথে আমার এই মতামতগুলির ব্যাকগ্রাউন্ড রয়েছে terms অবশ্যই যাকে যথেচ্ছ নির্ভুলতার প্রয়োজন হয় সে তথ্য প্রকার সম্পর্কে জানে তবে স্পষ্টত আমি সেই ব্যক্তি নই :) (তবে আমি খেয়াল করেছিলাম যে অব্কের আচরণ @ 2 ^ 53 + 1 অর্থাৎ ভাসমান দ্বিগুণ; ঠিক যথার্থতা এবং অভ্যন্তরীণ বনাম প্রিন্টিং ইত্যাদি আমার বাইরে) !)।

1
আপনি যদি শেলের বড় সংখ্যা নিয়ে কাজ করতে চান তবে bc, যেমন: ব্যবহার করুন $num=$(echo 6^6^6 | bc)। দুর্ভাগ্যক্রমে, bcলাইন বিরতি দেয়, তাই আপনাকে num=$(echo $num | sed 's/\\\s//g')পরে করতে হবে; আপনি যদি এটি কোনও পাইপে করেন তবে সত্যিকারের নতুন লাইন অক্ষর রয়েছে যা num=$(echo 6^6^3 | bc | perl -pne 's/\\\s//g')কাজ করে যদিও সেডের সাথে বিশ্রী । উভয় ক্ষেত্রেই আপনার এখন একটি পূর্ণসংখ্যা রয়েছে যা ব্যবহার করা যেতে পারে, যেমন num2=$(echo "$num * 2" | bc),।
স্বর্ণলোকস

1
... এখানে কেউ চিহ্নিত করেছেন যে আপনি bcসেট করে এই লাইন ব্রেক বৈশিষ্ট্যটি অক্ষম করতে পারবেন BC_LINE_LENGTH=0
স্বর্ণলোকস

উত্তর:


11

সুতরাং 2 ^ 63 থেকে 2 ^ 64-1 এর মধ্যে, আপনি উলঙ্গ_ম্যাক্স থেকে কতটা দূরে তা আপনাকে দেখিয়ে নেতিবাচক পূর্ণসংখ্যার পেতে পারেন।

না, আপনি এটি কীভাবে দেখেন? আপনার নিজের উদাহরণ দ্বারা, সর্বাধিক:

> max=$((2**63 - 1)); echo $max
9223372036854775807

যদি "ওভারফ্লো" বলতে বোঝায় যে "আপনি উলঙ্গ_ম্যাক্স থেকে আপনি কতটা দূরে রয়েছেন তা দেখিয়ে নেতিবাচক পূর্ণসংখ্যা পাওয়া যায়", তবে আমরা যদি এর সাথে যুক্ত করি, তবে কি আমাদের -1 পাওয়া উচিত নয়? কিন্তু এর পরিবর্তে:

> echo $(($max + 1))
-9223372036854775808

সম্ভবত আপনার অর্থ হ'ল এটি এমন একটি সংখ্যা যা আপনি $maxএকটি নেতিবাচক পার্থক্য পেতে যুক্ত করতে পারেন, যেহেতু:

> echo $(($max + 1 + $max))
-1

তবে বাস্তবে এটি সত্য ধরে রাখা যায় না:

> echo $(($max + 2 + $max))
0

কারণ এটি স্বাক্ষরিত পূর্ণসংখ্যাগুলি বাস্তবায়নের জন্য সিস্টেম দুটির পরিপূরক ব্যবহার করে । 1 ওভারফ্লো থেকে প্রাপ্ত মানটি আপনাকে কোনও পার্থক্য, নেতিবাচক পার্থক্য ইত্যাদি সরবরাহ করার চেষ্টা নয় এটি আক্ষরিক অর্থে একটি মানকে সীমিত সংখ্যক বিটগুলিতে কাটানোর ফলস্বরূপ, তারপরে এটি দুটির পরিপূরক স্বাক্ষরের পূর্ণসংখ্যার হিসাবে ব্যাখ্যা করা । উদাহরণস্বরূপ, কারণটি $(($max + 1 + $max))-1 হিসাবে প্রকাশিত হয়েছে কারণ দুটি পরিপূরকের সর্বোচ্চ মান হ'ল সর্বোচ্চ বিট ব্যতীত সমস্ত বিট সেট করা (যা নেতিবাচক ইঙ্গিত দেয়); এগুলি একসাথে যুক্ত করার অর্থ হ'ল সমস্ত বিটগুলি বামে বহন করে যাতে আপনার সাথে শেষ হয় (যদি আকারটি 16-বিট হয়, তবে 64 নয়):

11111111 11111110

উচ্চ (সাইন) বিটটি এখন সেট করা হয়েছে কারণ এটি সংযোজনটি চালিয়ে যায়। যদি আপনি এটিতে আরও একটি (00000000 00000001) যোগ করেন তবে আপনার তখন সমস্ত বিট সেট রয়েছে , যা দুটিটির পরিপূরক -1 is

আমি মনে করি যে আপনার প্রথম প্রশ্নের দ্বিতীয়ার্ধের আংশিক উত্তর দিয়েছে - "নেতিবাচক পূর্ণসংখ্যা কেন ... শেষ ব্যবহারকারীর সামনে উন্মুক্ত?" প্রথম, কারণ 64৪-বিট দুইয়ের পরিপূরক সংখ্যার বিধি অনুসারে এটি সঠিক মান। এটি বেশিরভাগ (অন্যান্য) সাধারণ উদ্দেশ্যে উচ্চ স্তরের প্রোগ্রামিং ভাষার প্রচলিত অনুশীলন (আমি এটির কাজ করে না এমন একটির কথা আমি ভাবতে পারি না), সুতরাং bashএটি কনভেনশনকে মেনে চলা। কোনটি প্রথম প্রশ্নের প্রথম অংশের উত্তর - "যুক্তি কী?": প্রোগ্রামিং ভাষার স্পেসিফিকেশনের ক্ষেত্রে এটিই আদর্শ।

দ্বিতীয় প্রশ্নটি ডাব্লুআরটি, আমি এমন সিস্টেমগুলির কথা শুনিনি যা আন্তঃনীতিতে ইউলং_ম্যাক্স পরিবর্তন করে।

যদি কেউ স্বেচ্ছায় স্বাক্ষরযুক্ত পূর্ণসংখ্যার মান সীমাবদ্ধতাগুলিতে সর্বাধিক পরিবর্তন করে তবে বাশটি পুনরুদ্ধার করে, আমরা কী আশা করতে পারি যে ঘটবে?

পাটিগণিতটি কীভাবে বেরিয়ে আসে তাতে কোনও পার্থক্য হবে না, কারণ এটি সিস্টেমটি কনফিগার করার জন্য ব্যবহৃত একটি নির্বিচার মান নয় - এটি একটি সুবিধার মান যা একটি হার্ডওয়্যার প্রতিবিম্বিত একটি অপরিবর্তনীয় ধ্রুবক সংরক্ষণ করে। সাদৃশ্য অনুসারে, আপনি 55 মাইল প্রতি ঘন্টা গ-এর পুনরায় সংজ্ঞা দিতে পারলেন , তবে আলোর গতি এখনও প্রতি সেকেন্ডে 186,000 মাইল থাকবে। সি মহাবিশ্বকে কনফিগার করার জন্য ব্যবহৃত একটি সংখ্যা নয় - এটি মহাবিশ্বের প্রকৃতি সম্পর্কে একটি ছাড়।

উলং_ম্যাক্স ঠিক একই রকম। এটি বি-বিট সংখ্যার প্রকৃতির উপর ভিত্তি করে কেটে নেওয়া / গণনা করা হয়। এটিকে পরিবর্তন করা limits.hখুব খারাপ ধারণা হবে যদি ধ্রুবকটি কোথাও ব্যবহার করে এটি সিস্টেমের বাস্তবতার প্রতিনিধিত্ব করে বলে মনে করা হয়

এবং আপনি আপনার হার্ডওয়্যার দ্বারা আরোপিত বাস্তবতা পরিবর্তন করতে পারবেন না।


১. আমি মনে করি না যে এটি (পূর্ণসংখ্যার উপস্থাপনের মাধ্যম) আসলে গ্যারান্টিযুক্ত bashকারণ এটি অন্তর্নিহিত সি লাইব্রেরির উপর নির্ভর করে এবং স্ট্যান্ডার্ড সি এর গ্যারান্টি দেয় না। তবে এটি বেশিরভাগ সাধারণ আধুনিক কম্পিউটারে ব্যবহৃত হয়।


আমি খুব কৃতজ্ঞ! ঘরে হাতির সাথে কথা বলে ভাবছি। হ্যাঁ প্রথম অংশে এটি বেশিরভাগ শব্দ সম্পর্কে। আমি কী বলতে চাইছিলাম তা প্রদর্শন করার জন্য আমি আমার প্রশ্ন আপডেট করেছি। দু'টির পরিপূরক কেন আমি যা দেখেছি তার কিছু বর্ণনা করে এবং আপনার উত্তরটি বুঝতে পেরে অমূল্য কেন তা আমি গবেষণা করব! যতদূর ইউনিক্স প্রশ্ন সংশ্লিষ্ট হয় আমি, AIX সঙ্গে ARG_MAX সম্পর্কে ভুল ব্যাখ্যা করা কিছু থাকতে হবে এখানে । চিয়ার্স!

1
আপনি যেমন বর্ণনা করেছেন তেমন আপনি যদি সীমা> ২ * এর মধ্যে থাকেন নিশ্চিত হন তবে আপনি মান নির্ধারণ করতে দু'টির পরিপূরক ব্যবহার করতে পারেন $max। আমার পয়েন্টগুলি হল 1) এটি উদ্দেশ্য নয়, 2) আপনি এটি করতে চান কিনা তা নিশ্চিত করুন, 3) খুব সীমিত প্রয়োগের কারণে এটি খুব কার্যকর নয়, 4) পাদটীকা অনুসারে এটি আসলে গ্যারান্টিযুক্ত নয় যে সিস্টেমটি করে দুটি পরিপূরক ব্যবহার করুন। সংক্ষেপে, প্রোগ্রাম কোডটিতে এটি কাজে লাগানোর চেষ্টা করা খুব খারাপ অভ্যাস হিসাবে বিবেচিত হবে। এখানে "বড় সংখ্যা" লাইব্রেরি / মডিউল রয়েছে (পসিক্সের অধীনে শেলগুলির জন্য bc) - আপনার প্রয়োজন হলে সেগুলি ব্যবহার করুন।
স্বর্ণলোকস

এটি সম্প্রতি সম্প্রতি আমি এমন কিছু দেখেছি যা দ্রুত বাহিত আইসি সহ 4-বিট বাইনারি অ্যাডারের সাথে একটি ALU বাস্তবায়নের জন্য দু'জনের পরিপূরককে উত্তোলন করেছিল; এমনকি তার পরিপূরকটির সাথে তুলনাও হয়েছিল (এটি দেখতে কীভাবে বন্ধ রয়েছে)। আপনার ভিডিওটি যে ভিডিওতে আলোচনা হয়েছে তার সাথে নাম লেখাতে এবং এখানে যা দেখলাম তার সাথে সংযোগ স্থাপন করতে সক্ষম হয়ে ওঠার জন্য আমার ব্যাখ্যা সহায়ক ছিল , সুযোগটি বাড়িয়ে আমি সত্যিই সমস্ত প্রভাবগুলি একবারে ডুবিয়ে ফেলতে পারব that এর জন্য আবারও ধন্যবাদ! চিয়ার্স!
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.