Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: Math::round not rounding correctly

by Laurent_R (Canon)
on Dec 23, 2014 at 22:46 UTC ( [id://1111249]=note: print w/replies, xml ) Need Help??


in reply to Math::round not rounding correctly

There are two different issues. One is the general issue about floating point arithmetic, with the problems between binary and decimal representations of floats, well covered for example in the What Every Computer Scientist Should Know About Floating-Point Arithmetic document that has already been mentioned. But this is only part of the story.

I have already stated that above, but no one seems to have noticed. The other problem is that the international IEEE standard for rounding numbers has enforced rules which are not what most people think. According to this international standard, the rule for true rounding is this: when you want to round a number with one decimal place to an integer, numbers whose decimal place is 5 will be rounded up when the previous digit is odd and down when the previous digit even. So that, when rounding to an integer, 1.5 and 2.5 should both be rounded to 2 .

Consider for example this illustration of true rounding according to international standards:

$ perl -e 'printf " %.1f => %.0f\n", $_, $_ for qw / .5 1.5 2.5 3.5 4 +.5 5.5 6.5 7.5 8.5 9.5/;' 0.5 => 0 1.5 => 2 2.5 => 2 3.5 => 4 4.5 => 4 5.5 => 6 6.5 => 6 7.5 => 8 8.5 => 8 9.5 => 10
This is what is considered correct. This is the international standard, and this is what the standard C library implements for the round function, and this is what Perl is also doing, presumably because it is based on the C library. (I have already explained in my post above the rationale for this apparently pesky rule.)

Now to your problem with 3461.5 and to what you have added in your successive edits of your post. If I want to round that number, I get this:

$ perl -e 'printf " %.0f \n", 3461.5;' 3462 $ perl -e 'printf " %.0f \n", 3462.5;' 3462
The last integer digit in 3461.5 is odd, so its gets rounded up. and 3462.5 is rounded down to the same number. Fair enough, that's the rule stated above.

Now when you using your multiplication for creating 3461.5:

$ perl -e 'printf " %.0f \n", 3010*1.15,' 3461
Why? Well, if you want to know, try this:
$ perl -e 'printf "%.15f \n", 3010*1.15,' 3461.499999999999545
As you can see, the internal representation of 3010*1.15 is actually slightly smaller than 3461.5, so it should logically be rounded down. This is due to the fact that 1.15 expressed in binary representation is periodical, i.e. a number with an infinite number of digits (just like 1/3 in decimal representation: 0.333333333...). If our computers were using internal decimal representation with, say, 13 decimal digits, 1/3 would have to be stored, say, as 0,3333333333333, meaning that the ...333... of the 14th, 15th, 16th, etc. digits are rounded down. Similarly, in binary format, 1.15 is truncated of some of its digits after a certain number of "decimal" places, to that the multiplication results in a number smaller than 3461.5. BTW, to get a, idea of the decimal value of the internal binary representation of 1.15, just try the same thing:
$ perl -e 'printf "%.19f \n", 1.15;' 1.1499999999999999112
A near miss, but not quite exactly 1.15.

And, by the way, just changing very slightly the numbers in your product yields the result you expect:

$ perl -e 'printf " %.0f \n", 301*11.5;' 3462
because 11.5 is not a periodical number in its binary representation. The difference between 301*11.5 and 3010*1.15 is:
$ perl -E 'say 301*11.5 - 3010*1.15;' 4.54747350886464e-13

Update: Corrected a typo in the second paragraph: "when the previous digit is odd" (and not "is off" as I had written). Thanks to N-Wing for picking it up.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1111249]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (4)
As of 2024-04-25 07:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found