我正在尝试解决这个bash脚本,该脚本从用户读取算术表达式并将其回显到输出屏幕,最后向上舍入3个小数位。
示例输入
5+50*3/20 + (19*2)/7
示例输出
17.929
我的代码是
read x
echo "scale = 3; $x" | bc -l
当输入
时5+50*3/20 + (19*2)/7
**我的输出是**
17.928
机器希望它
17.929
由于这个原因,我得到的解决方案是错误的。任何想法?
答案 0 :(得分:4)
这里的关键是确保使用格式规格为“%。3f”的printf,printf将根据您的意愿进行舍入,只要“scale = 4”为bc。
这是一个有效的脚本:
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。
或者,这也可以通过将here文档重定向为bc的输入而没有管道,如下所示,这样可以避免创建子shell:
echo -e "please enter math to calculate: \c"
read x
printf "%.3f\n" $(bc -l <<< "scale=4;$x")
答案 1 :(得分:3)
你没有四舍五入,你正在截断它。
$ 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
:
$ awk 'BEGIN { rounded = sprintf("%.3f", 5+50*3/20 + (19*2)/7); print rounded }'
17.929
所以,在你的例子中:
read x
awk 'BEGIN { rounded = sprintf("%.3f", $x; print rounded }'
答案 2 :(得分:1)
我完全同意jherran你没有对数字进行舍入,你是在截断它。我会继续说,规模可能只是没有按照你想要的方式表现,可能是没有人希望它表现的方式。
> 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,您将每个乘法/除法与加法分开。让我用一些例子证明我的观点:
> 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
然而,没有任何操作的比例也不起作用。有一个丑陋的解决方法:
> echo "scale=0; 5.5" | bc -l
5.5
> echo "scale=0; 5.5/1" | bc -l
5
因此,事情就会出现。
如果您想使用bc的缩放比例,请仅针对已计算的最终结果执行此操作,即便如此,请注意。
请记住,舍入与截断所需精度的数字+一半相同。
让我们以舍入到最接近的整数为例,如果将.5添加到应该向上舍入的数字,其整数部分将采用下一个整数值,截断将给出所需的结果。如果该数字应该向下舍入,那么添加.5将不会更改其整数值,并且截断将产生与添加任何内容时相同的结果。
因此我的解决方案如下:
> 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
再次注意,以下内容不起作用(如上所述),因此真正需要在两个操作中将其分解:
> echo "scale=3; ($x+0.0005)/1" | bc -l
17.928