This question already has answers here:
Is floating point math broken?

(30 个回答)


4年前关闭。




我有一个问题,我使用 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

我见过一些例子,其中计算中的浮点数可能会导致问题,但没想到格式化会出现这种情况。

最佳答案

数字 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 ,其中 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

关于awk - 使用 awk 和 printf 没有正确舍入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41083925/

10-11 20:44