Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

sprintf rounding convention

by jagaranga (Initiate)
on Oct 30, 2009 at 18:51 UTC ( #804204=perlquestion: print w/ replies, xml ) Need Help??
jagaranga has asked for the wisdom of the Perl Monks concerning the following question:

Was looking out for the rounding convention used by perl sprintf in-built function. I was thinking that it does a normal rounding (ROUND_HALF_UP - in Java's rounding mode convention - http://www.j2ee.me/javase/6/docs/api/java/math/RoundingMode.html), but the digging up further proved to be wrong. >> /usr/local/bin/perl5.10.1 -e 'print(sprintf("%.2f", shift @ARGV)."\n");' 0.335 0.34 >> /usr/local/bin/perl5.10.1 -e 'print(sprintf("%.2f", shift @ARGV)."\n");' 1.335 1.33

Comment on sprintf rounding convention
Re: sprintf rounding convention
by Joost (Canon) on Oct 30, 2009 at 19:22 UTC
    "Normal rounding" is a misleading term. As far as I know (and I can't be bothered to look it up) sprintf rounding uses whatever rounding libc uses, which tends but isn't guaranteed to be "banker's rounding". Banker's rounding, or HALF_EVEN in Java parlance*, is useful because it tends to lead to less distortion over large sums while still being predictable.

    * HALF_EVEN is also the strategy Java uses for float and double maths.

      That's incorrect. %f and other floating point specifiers always round to even. From F0convert:
      nv += 0.5; uv = (UV)nv; if (uv & 1 && uv == nv) uv--; /* Round to even */

      (There are paths I didn't take the time to understand, so maybe it doesn't always get to this function.)

        Now I'm confused:

        $ perl -v This is perl, v5.8.8 built for x86_64-linux-gnu-thread-multi $ perl -e 'printf "%.2f\n%.2f\n", 0.335, 1.335;' 0.34 1.33

        and

        C:\>perl -v This is perl, v5.8.9 built for MSWin32-x86-multi-thread (with 9 registered patches, see perl -V for more detail) C:\>perl -e "printf qq{%.2f\n%.2f\n}, 0.335, 1.335;" 0.34 1.34

        Am I missing something (as usual)?

        Update:

        Following ikegami's suggestion, I tried increasing the precision to 40 digits, and got:

        $ perl -v This is perl, v5.8.8 built for x86_64-linux-gnu-thread-multi $ perl -e 'printf "%.40f\n%.40f\n", 0.335, 1.335;' 0.3350000000000000199840144432528177276254 1.3349999999999999644728632119949907064438 C:\>perl -v This is perl, v5.8.9 built for MSWin32-x86-multi-thread (with 9 registered patches, see perl -V for more detail) C:\>perl -e "printf qq{%.40f\n%.40f\n}, 0.335, 1.335;" 0.3350000000000000200000000000000000000000 1.3350000000000000000000000000000000000000

        It looks like this variation is just an artifact of 64-bit vs. 32-bit, emphasizing how you should never rely on precise results from rounding.

        Hmm... Then I think the sprintf documentation is incorrect, or possibly just confusing: (emphasis mine)
        Perl does its own "sprintf" formatting--it emulates the C function "sprintf", but it doesn't use it (except for floating- point numbers, and even then only the standard modifiers are allowed). As a result, any non-standard extensions in your local "sprintf" are not available from Perl.
Re: sprintf rounding convention
by Anonymous Monk on Oct 30, 2009 at 19:23 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://804204]
Approved by Joost
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (13)
As of 2014-12-29 15:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (192 votes), past polls