views:

674

answers:

2

I was out looking for the rounding convention used by Perl's built-in function sprintf.

I was thinking that it does a normal rounding (e.g. ROUND_HALF_UP as in Java's rounding mode convention), but digging further proved this 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
+14  A: 

You have been bitten by the fact that floating point numbers are not exact representations of decimal fractions. Here's what I get:

  DB<1> $a=0.335

  DB<5> print sprintf("%.19f",$a)
0.3350000000000000200
  DB<7> $b=1.335

  DB<8> print sprintf("%.19f",$b)
1.3349999999999999645
  DB<9>

Since 0.335 is represented internally as slightly larger than 0.335 it rounds to .34, while 1.335 is slightly LESS than 1.335, so it rounds to 1.33.

Jim Garrison
+5  A: 

This is a function of IEEE floating point numbers.

For more information, in a Perl context, see Perlfaq4 "Does Perl have a round() function" and in particular what it says about half-way-point alternation.

jmcnamara