使用awk和printf无法正确舍入

时间:2016-12-11 07:24:31

标签: awk printf rounding

我有一个问题,我使用printf将浮点数舍入到正确的小数点数。我得到了不一致的结果,如下所示。

echo 104.45   |  awk '{printf "%.1f\n",$1}'
104.5                               <-- seem to be correct behaviour

echo 104.445  |  awk '{printf "%.2f\n",$1}'
104.44       (should be 104.45)     <-- seems to be INCORRECT behaviour

echo 104.4445 |  awk '{printf "%.3f\n",$1}'
104.445                             <-- seems to be correct behaviour

我已经看到过计算中的浮点数可能会导致问题的例子,但是没想到这会带来格式化。

3 个答案:

答案 0 :(得分:3)

数字104.4445不能完全表示为二进制数。换句话说,您的计算机不知道这样的数字。

# echo 104.4445 | awk '{printf "%.20f\n",$1}'
104.44450000000000500222

# echo 104.445 | awk '{printf "%.20f\n",$1}'
104.44499999999999317879

这就是为什么前者被四舍五入到104.445,而后者被四舍五入到104.44。

sjsam的答案仅与可以精确表示为二进制数的数字相关,即。即m/2**n,其中mn是整数而不是太大。将ROUNDINGMODE更改为“A”对打印104.45,104.445或104.4445绝对没有影响:

# echo 104.4445  |  awk -v ROUNDMODE="A" '{printf "%.3f\n",$1}'
104.445
# echo 104.4445 | awk '{printf "%.3f\n",$1}'
104.445
# echo 104.445 | awk -v ROUNDMODE="A" '{printf "%.2f\n",$1}'
104.44
# echo 104.445 | awk '{printf "%.2f\n",$1}'
104.44

答案 1 :(得分:1)

我在Python中尝试了类似的东西并得到了类似的结果:

_bla

这似乎是一致的浮动点浮动,特别是考虑到104.445的浮点表示小于实际数学值104.445:

>>> round(104.445, 2)
104.44
>>> round(104.4445, 3)
104.445

答案 2 :(得分:0)

我强烈怀疑这种行为的原因与awk的关系不如计算机存储数字的方式。正如user31264所述:&#34;您的计算机不知道这样的数字[如104.4445]。&#34;

以下是我在Pale Moon Web浏览器中使用JavaScript Scratchpad进行的实验结果:

(104.45).toFixed(55)
/*
104.4500000000000028421709430404007434844970703125000000000
*/

(104.445).toFixed(55)
/*
104.4449999999999931787897367030382156372070312500000000000
*/

(104.4445).toFixed(55)
/*
104.4445000000000050022208597511053085327148437500000000000
*/

很可能,你的awk解释器不处理十进制数104.45等,而是使用&#34; wonky&#34;这里显示的值。围绕其中的第一,第二和第三个&#34; wonky&#34;分别为1,2和3个小数位的值将给出与awk解释器给你相同的结果。