为什么 bash 算术中的除法将大多数百分比计算为 0?

Cyb*_*beX 15 command-line bash scripts

尝试对脚本进行 bash 算术运算,但$e直到最后才更新。输出不言自明。

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

Tl;DR:以百分比形式显示 1..5。

输出 :

echo 1 / 5 : = 0
echo 2 / 5 : = 0
echo 3 / 5 : = 0
echo 4 / 5 : = 0
echo 5 / 5 : = 100
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

sou*_* c. 25

bash不能处理非整数算术。只要所有表达式都是整数,它就会给你正确的结果。因此,您需要避免在计算中的某处获得非整数值。

在您的情况下,当您评估等时1 / 52 / 5它会在 bash 中创建与某些非整数值相对应的整数零值,并且结果相应地为零。除法和乘法的优先级是相同的,并且相同的先行运算符总是从左到右执行,因为它们被放置在表达式中。

一种解决方法是先进行乘法,然后进行除法,这样 bash 就不必处理非整数值。更正后的表达式将是,

$ 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
Run Code Online (Sandbox Code Playgroud)


Zan*_*nna 16

Bash 在这种算术上做得不是很好......这是你的问题:

$ echo $((1/5))
0
$ echo $((2/5))
0
$ echo $((4/5))
0
$ echo $((4/5))
0
Run Code Online (Sandbox Code Playgroud)

如果需要处理非整数值,可以使用 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
Run Code Online (Sandbox Code Playgroud)

(感谢@Arronical 指出如何将输出格式化为整数)


Joh*_*024 11

与 bash 不同,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
Run Code Online (Sandbox Code Playgroud)


alf*_*red 5

尝试

percent=$(( $e*100/$max ))
Run Code Online (Sandbox Code Playgroud)

:)

请参阅以下的算术评估部分:

man bash
Run Code Online (Sandbox Code Playgroud)

它只支持整数。