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.


In reply to Re: Math::round not rounding correctly by Laurent_R
in thread Math::round not rounding correctly by bulrush

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.