首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bc算术误差

bc算术误差
EN

Stack Overflow用户
提问于 2014-12-07 07:32:17
回答 3查看 940关注 0票数 9

我正在试图解决这个bash脚本,它从用户读取一个算术表达式,并将其回显到输出屏幕,最后将其舍入小数点3位。

样本输入

代码语言:javascript
复制
5+50*3/20 + (19*2)/7

样本输出

代码语言:javascript
复制
17.929

我的代码是

代码语言:javascript
复制
read x
echo "scale = 3; $x" | bc -l

当有一个输入时

代码语言:javascript
复制
5+50*3/20 + (19*2)/7

**我的产出是**

代码语言:javascript
复制
17.928

,机器希望它是

代码语言:javascript
复制
17.929

正因为如此,我把解决方案搞错了。知道吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-12-07 08:29:33

这里的关键是确保使用带有"%.3f“格式规范的printf,而printf将按照您的意愿进行舍入,只要bc使用"scale=4”即可。

下面是一个实用的脚本:

代码语言:javascript
复制
echo -e "please enter math to calculate: \c"
read x
printf "%.3f\n" $(echo "scale=4;$x" | bc -l)

如果您在命令行:echo "scale=4;5+50*3/20 + (19*2)/7" | bc上运行以下命令,您可以了解上面的解决方案是什么,结果将是17.9285。当将该结果作为参数提供给printf时,函数将考虑到第四位小数位并将值舍入,以便格式化后的结果显示为精确的三个小数位,值为17.929。

或者,通过将这里的文档重定向为bc的输入,这也不需要管道,如下所示,它避免了创建子shell:

代码语言:javascript
复制
echo -e "please enter math to calculate: \c"
read x
printf "%.3f\n" $(bc -l <<< "scale=4;$x")
票数 5
EN

Stack Overflow用户

发布于 2014-12-07 07:42:55

你不是在舍入这个数字,而是在截断它。

代码语言:javascript
复制
$ echo "5+50*3/20 + (19*2)/7" | bc -l
17.92857142857142857142
$ echo "scale = 3; 5+50*3/20 + (19*2)/7" | bc -l
17.928

我知道的唯一能使数字四舍五入的方法是使用awk

代码语言:javascript
复制
$ awk  'BEGIN { rounded = sprintf("%.3f", 5+50*3/20 + (19*2)/7); print rounded }'
17.929

所以,在你的例子中:

代码语言:javascript
复制
read x
awk  'BEGIN { rounded = sprintf("%.3f", $x; print rounded }'
票数 3
EN

Stack Overflow用户

发布于 2014-12-07 15:21:25

我完全同意jherran的观点,你不是在舍入这个数字,而是在截断它。我会继续说,规模可能只是没有表现出你想要的样子,可能没有人希望它表现出来。

代码语言:javascript
复制
> x="5+50*3/20 + (19*2)/7"
> echo "$x" | bc -l
17.92857142857142857142
> echo "scale = 3; $x" | bc -l
17.928

此外,because of the behaviour of scale,您将每个乘法/除法与加法分开。让我用一些例子来证明我的观点:

代码语言:javascript
复制
> echo "scale=0; 5/2" | bc -l
2
> echo "scale=0; 5/2 + 7/2" | bc -l
5
> echo "5/2 + 7/2" | bc -l
6.00000000000000000000

然而,没有任何操作的比例也不起作用。有一个丑陋的解决方案:

代码语言:javascript
复制
> echo "scale=0; 5.5" | bc -l
5.5
> echo "scale=0; 5.5/1" | bc -l
5

这里面有两件事。

  • 如果您想要使用bc的规模,只对已经计算的最终结果执行,即使这样,也要小心。
  • 请记住,舍入等于截断一个数字+所需精度的一半。

让我们以舍入最近的整数为例,如果将.5加到一个应该舍入的数字中,它的整数部分将取下一个整数值,截断将给出所需的结果。如果这个数字应该是四舍五入的,那么添加.5不会改变它的整数值,截断将产生与未添加的结果相同的结果。

因此,我的解决办法如下:

代码语言:javascript
复制
> y=$(echo "$x" | bc -l)
> echo "scale=3; ($y+0.0005)/1" | bc -l # scale doesn't apply to the +, so we get the expected result
17.929

同样,请注意以下内容不起作用(如上文所述),因此需要将其分为两个操作:

代码语言:javascript
复制
> echo "scale=3; ($x+0.0005)/1" | bc -l
17.928
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27340666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档