Why is the sprintf around the fractional part of 5.555 and 0.555 different?

Can someone explain why there is a difference in behavior here?

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

I read that sprintf() rounded if the following digits are 5 or more. So why is it not rounded to 0.56 in the second case?

+5
source share
3 answers

The nearest 64-bit IEEE 754 floating-point binary number to 0.555 is 0.55500000000000004884981308350688777863979339599609375. This is very slightly closer to 0.56 than to 0.55.

The nearest 64-bit IEEE 754 floating-point binary number to 5.555 is 5.55499999999999971578290569595992565155029296875. This is very slightly closer to 5.55 than to 5.56.

In each case, the output is the nearest decimal number with 2 decimal places to the actual value of the extension number.

As Pascal Quoc says in a comment, 0.555 is located in binade [0.5 ... 1), in which representable floating-point numbers are separated by 2 -53 . On the contrary, 5.555 is in binad [4 ... 8), in which representable floating-point numbers are divided by 2 -50 . That is why the fractional parts differ for 0.555 and 5.555.

+9
source

Since printf rounds the value, just try:

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

gives:

 5.5549999999999997157829057 

rounded to 5.55 using printf('%.2f', 5.55)

and

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

gives

 0.5550000000000000488498131 

rounded to 0.56 using printf('%.2f', 0.55)

+5
source

If you want more consistent results, check out 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 
+1
source

Source: https://habr.com/ru/post/1202403/


All Articles