bash
शेल की अंकगणितीय मूल्यांकन क्षमताओं के लिए सीमाएं निर्धारित हैं । शेल अंकगणित लेकिन राज्यों के इस पहलू के बारे में मैनुअल पर्याप्त है :
अति-प्रवाह के लिए कोई जांच नहीं के साथ निश्चित-चौड़ाई के पूर्णांकों में मूल्यांकन किया जाता है, हालांकि 0 से विभाजन फंस जाता है और एक त्रुटि के रूप में चिह्नित किया जाता है। संचालक और उनकी पूर्वता, सहानुभूति और मूल्य C भाषा में समान हैं।
कौन-सी निश्चित-चौड़ाई पूर्णांक यह संदर्भित करता है कि वास्तव में किस डेटा प्रकार का उपयोग किया जाता है (और यह क्यों है, इसकी बारीकियों के बारे में), लेकिन सीमा मूल्य /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
भी आदि मैं नियमित अभिव्यक्ति मैं इस्तेमाल किया मनमाना परिशुद्धता उपकरण जैसे मैं के बारे में कुछ भी पकड़ नहीं कर रहा है bc
और dc
।
प्रशन
- आपको चेतावनी न देने का औचित्य क्या है (जैसे
awk
2 ^ 1024 का मूल्यांकन करते समय) जब आपके अंकगणितीय मूल्यांकन ओवरफ्लो होते हैं? 2 63 और 2 64 -1 के बीच नकारात्मक पूर्णांक अंतिम उपयोगकर्ता के सामने क्यों आते हैं, जब वह किसी चीज का मूल्यांकन कर रहा होता है? - मैंने कहीं पढ़ा है कि UNIX का कुछ स्वाद ULONG_MAX को अंतःक्रियात्मक रूप से बदल सकता है? क्या किसी ने इस बारे में सुना है?
- यदि कोई अनियंत्रित पूर्णांक के मान को अधिकतम रूप से बदलता है
limits.h
, तो recompilesbash
, हम क्या उम्मीद कर सकते हैं?
ध्यान दें
1. मैं और अधिक स्पष्ट रूप से वर्णन करना चाहता था कि मैंने क्या देखा, क्योंकि यह बहुत ही सरल अनुभवजन्य सामान है। मैंने देखा है कि:
- (ए) कोई भी मूल्यांकन जो <२ ^ ६३-१ देता है वह सही है
- (b) कोई भी मूल्यांकन जो => २ ^ ६३ से २ ^ ६४ देता है एक नकारात्मक पूर्णांक देता है:
- उस पूर्णांक की सीमा x से y है। x = -922337203685474780808 और y = 0।
इसे देखते हुए, एक मूल्यांकन जो (बी) 2 ^ 63-1 के रूप में व्यक्त किया जा सकता है और x..y के भीतर कुछ है। उदाहरण के लिए अगर हमें सचमुच मूल्यांकन करने के लिए कहा जाता है (2 ^ 63-1) +100 002 (लेकिन (a) की तुलना में कोई संख्या छोटी हो सकती है) तो हमें -9223372036854675807 मिलता है। मैं केवल स्पष्ट अनुमान लगा रहा हूं, लेकिन इसका मतलब यह है कि दो निम्नलिखित भाव हैं:
- (2 ^ 63-1) + 100 002 और;
- (2 ^ 63-1) + (LLONG_MAX - {शेल हमें क्या देता है ((2 ^ 63-1) + 100 002), जो कि -9223372036854675807} है;
- (2 ^ 63-1) + (9223372036854775807 - 9223372036854675807 - 100%)
- = 922337203685474780807 + 100 000
वास्तव में बहुत करीब हैं। दूसरी अभिव्यक्ति "2" के अलावा (2 ^ 63-1) + 100 002 है, जिसका हम मूल्यांकन कर रहे हैं। इसका मतलब है कि आपके द्वारा नकारात्मक पूर्णांक आपको दिखाते हैं कि आप 2 ^ 64 से कितने दूर हैं। मेरा मतलब है कि उन नकारात्मक पूर्णांकों और सीमाओं के ज्ञान के साथ, अच्छी तरह से आप मूल्यांकन को x..y रेंज में बैश शेल में समाप्त नहीं कर सकते हैं, लेकिन आप कहीं और कर सकते हैं - डेटा उस अर्थ में 2 ^ 64 तक उपयोग करने योग्य है (मैं जोड़ सकता हूं) यह कागज पर है या इसे bc में उपयोग करें)। इसके अलावा कि व्यवहार 6 ^ 6 ^ 6 के समान है, क्योंकि सीमा क्यू में नीचे वर्णित है ...
bc
, उदाहरण के लिए $num=$(echo 6^6^6 | bc)
:। दुर्भाग्य से, bc
लाइन ब्रेक में डालता है, इसलिए आपको num=$(echo $num | sed 's/\\\s//g')
बाद में करना होगा; यदि आप इसे एक पाइप में करते हैं, तो वास्तविक newline वर्ण हैं, जो कि sed के साथ अजीब हैं, हालांकि num=$(echo 6^6^3 | bc | perl -pne 's/\\\s//g')
काम करता है। या तो आपके पास अब एक पूर्णांक है, जिसका उपयोग किया जा सकता है, जैसे num2=$(echo "$num * 2" | bc)
।
bc
सेटिंग द्वारा इस लाइन ब्रेक सुविधा को अक्षम कर सकते हैं BC_LINE_LENGTH=0
।