Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Perl's sprintf not round floating point numbers correctly?

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
like image 694
Jaga Avatar asked Oct 30 '09 18:10

Jaga


2 Answers

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.

like image 85
Jim Garrison Avatar answered Nov 17 '22 13:11

Jim Garrison


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.

like image 32
jmcnamara Avatar answered Nov 17 '22 13:11

jmcnamara