bc 的浮点运算不精确?

bc 的浮点运算不精确?

当我使用 bc 在 shell 中执行浮点运算时,如果我使用常规计算器,结果会有所不同。难道我做错了什么?

例如,我需要找到球体的体积。用户输入半径值。

pi = 3.14

volume=$(echo "scale = 2; (4 / 3) * $pi * ($r ^ 3)" | bc)
echo "Volume is $volume"

如果半径 = 3,unix 返回 112.59,计算器返回 113.1。

答案1

你需要理解的含义表达式的规模bcbc可以做任意精度(这并不一定意味着无限的精度)而你的计算器可能具有处理器的精度float或数据类型。double

bc。这规模是点后的小数位数,所以与精度有关。这规模表达式的值是根据规则确定的,这些规则取决于所涉及的运算符和scale变量(该变量是给出表达式的变量)随意的的维度精确也就是说bc,这可以使其精度达到您想要的程度)。

例如,除法结果的小数位数是scale。所以4/3scale是 2时1.33,是 的一个非常粗略的近似值4/3。的尺度x * y将是min(a+b,max(scale,a,b))(其中a是 的尺度xb的尺度y),所以这里2。也会1.33 * 3.14如此4.17

对于规则,您可以查看POSIX 规范bc

如果您想要更高的精度,请增加scale。您可以无限期地增加它。使用bc -l,scale会自动设置为20

$ pi='(a(1)*4)' r=3
$ $ echo "(4 / 3) * $pi * ($r ^ 3)" | bc -l
113.09733552923255658339

$ echo "scale=1000; (4 / 3) * $pi * ($r ^ 3)" | bc -l
113.0973355292325565846551617980621038310980983775038095550980053230\
81390626303523950609253712316214447357331114478163039295378405943820\
96034211293869262532022821022769726978675980014720642616237749375071\
94371951239736040606251233364163241939497632687292433484092445725499\
76355759335682169861368969085854085132237827361174295734753154661853\
14730175311724413325296040789909975753679476982929026989441793959006\
17331673453103113187002257495740245517842677306806456786589844246678\
87098096084205774588430168674012241047863639151096770218070228090538\
86527847499397329973941181834655436308584829346483609858475202045257\
72294881898002877683392804259302509384339728638724440983234852757850\
73357828522068813321247512718420036644790591105239053753290671891767\
15857867345960859999994142720979823815034238137946746942088054039248\
86988951308030971204086612694295227741563601129621951039171511955017\
31142218396089302929537125655435196874321744263099764736353375070480\
1468800991581641650380680694035580030527317911271523

$ echo "scale=1; (4 / 3) * $pi * ($r ^ 3)" | bc -l
97.2

您还可以使用 high 进行所有计算scale,并最终减少它以进行显示:

$ echo "scale=10; (4 / 3) * $pi * ($r ^ 3)" | bc -l
113.0973355107
$ echo "scale=100; x = (4 / 3) * $pi * ($r ^ 3); scale = 10; x / 1" | bc -l
113.0973355292

答案2

您应该使用更好的值pi并允许比例按照默认定义bc(20 位数字):

$ echo "r=3; pi=4*a(1); (4/3)*pi*(r^3)" | bc -l
113.09733552923255658339

这是执行计算的更好方法。比例是定义计算中使用的精度的参数,而不是格式化结果的数字输出的参数。

要格式化数字,您可以使用 printf:

$ result="$(echo "r=3; pi=4*a(1); (4/3)*pi*(r^3)" | bc -l)"
$ printf '%.2f' "$result"
113.10

,如果您在使用数字小数字符(或)时遇到麻烦.,您可以使用此版本:

$ LC_NUMERIC=C printf '%.2f' "$result"
113.10

printf 按照 IEEE 754 实现对数字进行四舍五入

当然,您可以通过最后更改比例来强制 bc 削减小数:

$ echo "r=3; pi=4*a(1); res=(4/3)*pi*(r^3); scale=2; res/1" | bc -l
113.09

但总的来说,这是一个坏主意。

相关内容