5

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
brian d foy
  • 129,424
  • 31
  • 207
  • 592
Jaga
  • 393
  • 2
  • 5
  • 15
  • 7
    print(sprintf(...))? I wonder if there is a "printf"... – jrockway Oct 31 '09 at 05:31
  • 1
    Have a look at [Perl Cookbook recipe 2.2 - rounding floating-point numbers](http://books.google.com/books?id=hP4IRp8xwTkC&pg=PA64&lpg=PA64&dq=rounding+numbers+perl+cookbook&source=bl&ots=ti7Tyxr3s7&sig=gyWX-iySyiVZef0vB43ZuIaxkuw&hl=en&ei=RPzrStmzO4z0MarIvKkI&sa=X&oi=book_result&ct=result&resnum=1&ved=0CAwQ6AEwAA#v=onepage&q=&f=false) for a more complete explanation – heferav Oct 31 '09 at 09:12

2 Answers2

16

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
  • 85,615
  • 20
  • 155
  • 190
6

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
  • 38,196
  • 6
  • 90
  • 108