使用awk和printf未正确舍入

使用awk和printf未正确舍入,awk,printf,rounding,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) <-

我有一个问题,我使用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
echo 104.45 | awk'{printf'%.1f\n',$1}'

104.5数字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的答案仅与可以精确表示为二进制数的数字有关,即。e
m/2**n
,其中
m
n
是整数,不太大。将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

我在Python中尝试了类似的方法,得到了类似的结果:

>>> round(104.445, 2)
104.44
>>> round(104.4445, 3)
104.445
这似乎是普通的浮点不稳定,特别是考虑到104.445的浮点表示法小于104.445的实际数学值:

>>> 104.445 - 104.44
0.0049999999999954525
>>> 104.445 - 104.44 + 104.44
104.445

我强烈怀疑这种行为的原因与其说与awk有关,不如说与计算机存储数字的方式有关。正如user31264所说:“您的计算机不知道这样一个数字[如104.4445]。”

以下是我刚刚在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等,而是处理此处显示的“不稳定”值。将这些“WOKY”值的第一、第二和第三分别舍入到1, 2位和3位小数点将给出与AWK解释器给你相同的结果。

你使用AWCK的<代码> GNU<代码>版本吗?为了更接近的问题,请参见。在格式化的上下文中,我不希望出现任何数字表示问题,只是字符串缩短或填充。只有第二个案例的行为符合我的预期。