为什么sprintf以5.555和0.555的小数部分不同?

时间:2014-09-12 07:28:47

标签: perl floating-point printf rounding

有人可以解释为什么这里的行为存在差异吗?

perl -E 'say sprintf("%.2f",5.555);'
5.55    

perl -E 'say sprintf("%.2f",0.555);'
0.56  

如果以下数字为5或更大,我已经读过sprintf()四舍五入。那么为什么在第二种情况下它没有达到0.56呢?

3 个答案:

答案 0 :(得分:9)

最接近的IEEE 754 64位二进制浮点数为0.555是0.55500000000000004884981308350688777863979339599609375。它略微接近0.56而不是0.55。

最接近的IEEE 754 64位二进制浮点数为5.555是5.55499999999999971578290569595992565155029296875。它略微接近5.55而不是5.56。

在每种情况下,输出都是最接近的十进制数,其中包含内部数字实际值的2位小数。

正如Pascal Cuoq在评论中所说,0.555位于binade [0.5 ... 1],其中可表示的浮点数由2 -53 分隔。相比之下,5.555位于binade [4 ... 8]中,其中可表示的浮点数由2 -50 分隔。这就是0.555和5.555的小数部分不同的原因。

答案 1 :(得分:5)

因为printf会对值进行舍入,只需尝试:

perl -e 'printf("%.25f", 5.555)'

给出:

5.5549999999999997157829057

使用5.55

四舍五入到printf('%.2f', 5.55)

perl -e 'printf("%.25f", 0.555)'

给出

0.5550000000000000488498131

使用0.56

四舍五入到printf('%.2f', 0.55)

答案 2 :(得分:1)

如果您想获得更一致的结果,请查看Math::Round

perl -MMath::Round=:all -E 'say nearest(.01, 0.555)'
0.56

perl -MMath::Round=:all -E 'say nearest(.01, 5.555)'
5.56