This is my first post here, so please excuse my bad english.

Working on a larger project we needed some code to round numbers (that are prices in a shop) to a precision of 2 digits (%.2f), i.e. from 8.7385 to 8.74. In 'Programming perl', or in the monastery you find this code:
sub round($$) { sprintf "%.$_[1]f",$_[0]; } print round(8.7385, 2); # prints 8.74
which works really nice... until we found out following strange behaviour:
for my $i (0 .. 10) { print round($i+0.555,2)," "; } # which prints: # 0.56 1.56 2.56 3.56 4.55 5.55 6.55 7.55 8.55 9.55 10.56
...hm, the decimal part should allways be the same!
from 10 upwards it seems to stay '.56', but now look at this:
for (my $i = 1; $i < \xFFFF; $i <<= 1) { print round($i+0.555,2), " "; } # which prints: #1.56 2.56 4.55 8.55 16.56 32.56 64.56 128.56 256.56 512.55 #1024.56 2048.55 4096.56 8192.56 16384.56 32768.56 65536.55 #131072.55 262144.55 524288.56 1048576.55 2097152.56 4194304.55 #8388608.55 16777216.56 # #(You can try with different numbers and different precision as long # as the last digit is '5' and the precision = number of digits - 1)
So here goes my first question:

- Is there a 'mystical rule' behind this behaviour? (Is ist a bug or is it a feature?)
(Btw. i've tested on Linux and different Windows Systems, Activestate 5.005/5.6.)

And the 2nd question:

I wrote this code to achieve same behaviour (and allways print %.2f in the shop):
sub round2($$) { my $var=$_[0]; my $decimal=($var-int(var)); if ($decimal && ((length($decimal)-2)>$_[1]) && ($var=~/5$/)) { $var=~s/5$/6/; } sprintf "%.$_[1]f",$var; } # some output: for (my $i = 1; $i < \xFFFF; $i <<= 1) { print round($i+0.555,2), " ", round2($i+0.555,2), "\n"; }
...but it's somewhat obfuscated (and it does not take care of numbers like 1.5E-4).

So any ideas or comments would be appreciated.

In reply to strange rounding behaviour by Anonymous Monk

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.