เหตุใดการหารในการคำนวณทางคณิตศาสตร์จึงคำนวณเปอร์เซ็นต์ส่วนใหญ่เป็น 0


15

การพยายามใช้ bash arithemetic สำหรับสคริปต์ แต่$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
ที่เกี่ยวข้อง: ทุบตีเพียงให้จำนวนเต็มเป็นเอาท์พุทโดยไม่คำนึงถึงการป้อนข้อมูลเมื่อทำการคำนวณ (แม้ว่าแตกต่างจากปัญหาที่อธิบายไว้ที่นี่ที่ไม่สามารถแก้ไขได้โดยการจัดเรียงการดำเนินงาน)
Eliah Kagan

คำตอบ:


24

bashไม่สามารถจัดการเลขคณิตที่ไม่ใช่จำนวนเต็มได้ มันจะให้ผลลัพธ์ที่ถูกต้องตราบใดที่นิพจน์ทั้งหมดเป็นจำนวนเต็ม ดังนั้นคุณต้องหลีกเลี่ยงการรับค่าที่ไม่ใช่จำนวนเต็มในการคำนวณของคุณ

ในกรณีของคุณเมื่อคุณมีการประเมิน1 / 5, 2 / 5ฯลฯ มันจะสร้างจำนวนเต็มค่าศูนย์ใน correspondings ทุบตีบางค่าที่ไม่ใช่จำนวนเต็มและผลที่จะออกมาเป็นศูนย์ตาม ความสำคัญของการหารและการคูณเป็นตัวดำเนินการที่เหมือนกันและเหมือนกันเสมอจะถูกดำเนินการจากซ้ายไปขวาตามที่วางไว้ในนิพจน์

หนึ่งรอบ ๆ จะทำการคูณก่อนแล้วหารดังนั้นทุบตีไม่ต้องจัดการค่าที่ไม่ใช่จำนวนเต็ม การแสดงออกที่ถูกต้องจะเป็น

$ 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
subexpression 1/5ไม่ได้สร้างจำนวนเต็มไม่ใช่ค่า มันสร้างค่าจำนวนเต็ม0เนื่องจากผลลัพธ์ของการหารจำนวนเต็ม 1 ถึง 5 คือ 0 การดำเนินการเพิ่มเติมใช้ค่า0นั้นเป็นผลสำเร็จ นี่ไม่ใช่สิ่งที่ OP ต้องการ แต่การดำเนินการไม่มีการสร้างค่าที่ไม่ใช่จำนวนเต็มและไม่มีการดำเนินการที่ล้มเหลว
Eliah Kagan

@EliahKagan ขอบคุณสำหรับการชี้ให้เห็นข้อบกพร่อง แก้ไข
souravc

16

Bash ทำคณิตศาสตร์ในเลขคณิตได้ไม่ดีนัก ... นี่คือปัญหาของคุณ:

$ 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 สำหรับการชี้วิธีจัดรูปแบบเอาต์พุตเป็นจำนวนเต็ม)


แน่นอนฉันจะดูในนี้ขอบคุณอีกครั้ง!
Cybex

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 ))

:)

ดูส่วนการประเมินผลทาง ARITHMETIC จาก:

man bash

รองรับเฉพาะจำนวนเต็มเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.