बैश अंकगणित में विभाजन सबसे अधिक प्रतिशत के रूप में 0 क्यों है?


15

एक स्क्रिप्ट के लिए बैश आरैथमेटिक का प्रयास करना, लेकिन $eअंत तक अपडेट नहीं होता है। आउटपुट अपने लिए बोलता है।

max=5
for e in $(seq 1 1 $max); do 
    percent=$(( $e/$max*100 ))
    echo "echo $e / $max : = $percent"
done

Tl; DR: 1..5 प्रतिशत के रूप में प्रदर्शित करें।

आउटपुट:

echo 1 / 5 : = 0
echo 2 / 5 : = 0
echo 3 / 5 : = 0
echo 4 / 5 : = 0
echo 5 / 5 : = 100

ऐसा क्यों है?


1
संबंधित: बैश केवल गणना करते समय इनपुट की परवाह किए बिना आउटपुट के रूप में पूर्णांक देता है (हालांकि, यहां वर्णित समस्या के विपरीत, जो कि संचालन को फिर से व्यवस्थित करके अच्छी तरह से हल नहीं किया जा सकता है।)
एलियाह कगन

जवाबों:


24

bashगैर-पूर्णांक अंकगणित को संभाल नहीं सकते। यह आपको सही परिणाम देगा जब तक कि सभी भाव पूर्णांक नहीं होते। इसलिए आपको अपनी गणना में एक गैर-पूर्णांक मान प्राप्त करने से बचने की आवश्यकता है।

आपके मामले में, जब आप मूल्यांकन कर रहे होते हैं 1 / 5, 2 / 5आदि , तो यह कुछ गैर-पूर्णांक मानों के आधार पर पूर्णांक शून्य मान बनाता है और परिणाम तदनुसार शून्य हो रहे हैं। पूर्वता विभाजन और गुणा के समान है और एक ही मिसाल ऑपरेटरों हमेशा बाएं से दाएं क्रियान्वित कर रहे हैं के रूप में वे अभिव्यक्ति में रखा जाता है कर रहे हैं।

चारों ओर एक काम पहले गुणा करना होगा और फिर विभाजन को कभी भी गैर-पूर्णांक मान को संभालना नहीं होगा। सही अभिव्यक्ति होगी,

$ max=5; for e in $(seq 1 1 $max); do percent=$(( $e*100/$max )); echo "echo $e / $max : = $percent"; done
echo 1 / 5 : = 20
echo 2 / 5 : = 40
echo 3 / 5 : = 60
echo 4 / 5 : = 80
echo 5 / 5 : = 100

1
उप-संपीड़न 1/5एक गैर-पूर्णांक मान नहीं बनाता है । यह पूर्णांक मान बनाता है 0, क्योंकि 1 के 5 से पूर्णांक विभाजन का परिणाम 0. है। आगे के संचालन सफलतापूर्वक उस मूल्य का उपयोग करते हैं 0। यह ओपी का इरादा नहीं है, लेकिन कोई भी ऑपरेशन एक गैर-पूर्णांक मान नहीं बनाता है और कोई भी ऑपरेशन विफल नहीं होता है।
एलियाह कगन

@EliahKagan ने इसे दोष बताने के लिए धन्यवाद दिया। संपादित।
सप्तऋषि

16

बैश इस तरह के अंकगणित में बहुत अच्छा नहीं करता है ... यहाँ आपकी समस्या है:

$ echo $((1/5))
0
$ echo $((2/5))
0
$ echo $((4/5))
0
$ echo $((4/5))
0

यदि आपको गैर-पूर्णांक मानों को संभालने की आवश्यकता है, तो आप उपयोग कर सकते हैं bc

$ max=5; for e in $(seq 1 1 "$max"); do percent=$(bc <<< "scale=1 ; $e/$max*100") ; echo "echo $e / $max : = ${percent%.*}"; done
echo 1 / 5 : = 20
echo 2 / 5 : = 40
echo 3 / 5 : = 60
echo 4 / 5 : = 80
echo 5 / 5 : = 100

(पूर्णांक के रूप में आउटपुट को प्रारूपित करने के तरीके के लिए @Arronical का धन्यवाद)


मैं निश्चित रूप से इस पर एक नज़र होगा, एक बार फिर धन्यवाद!
साइबेक्स

1
आप अपनी इको में .0बदलकर आउटपुट से ट्रिम कर सकते हैं :)$percent${percent%.*}
Arronical

11

बैश के विपरीत, awk पूर्ण फ़्लोटिंग पॉइंट अंकगणित प्रदान करता है। उदाहरण के लिए:

$ awk -v max=5 'BEGIN{for (e=1;e<=max;e++) print "echo " e " / " max " : = " 100*e/max}' 
echo 1 / 5 : = 20
echo 2 / 5 : = 40
echo 3 / 5 : = 60
echo 4 / 5 : = 80
echo 5 / 5 : = 100

5

प्रयत्न

percent=$(( $e*100/$max ))

:)

अनुभाग देखें:

man bash

यह केवल पूर्णांक का समर्थन करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.