On Wed, Sep 01, 2010 at 04:46:30PM -0400, Jim wrote: > Can anyone comment how they handle floating point precision situations > like this? > > Here is a basic toy program: > #!/usr/bin/perl > > use strict; > > my $total = 0; > my $a = 21835.30; > my $b = -21715.90; > my $c = 9652.20; > my $d = -9771.60; > > print ("total = $total\n"); > $total += $a; > print ("total = $total\n"); > $total += $b; > print ("total = $total\n"); > $total += $c; > print ("total = $total\n"); > $total += $d; > print ("total = $total\n"); > $total = sprintf("%.2f", $total); > print ("total = $total\n"); > > > And here is the output: > total = 0 > total = 21835.3 > total = 119.399999999998 > total = 9771.6 > total = -1.81898940354586e-12 > total = -0.00 > > Note the lack of precision adding these simple numbers which do not have > a large number of digits to the right of the decimal. > > If the line: > $total = sprintf("%.2f", $total); > would produce 0.00 rather than -0.00 I could live with this. > > But the only solution I have to get the final answer to properly be 0.00 > is to format > $total = sprintf("%.2f", $total); > after each increment is added to $total > > or maybe put a string comparison at the end checking for "-0.00" and > changing it to "0.00" if it matches. > > I don't like either of these solutions. > > How do others deal with this?
Depending on exactly what you require, something like this might do what you want: #!/usr/bin/perl use strict; my $total = 0; my $a = 21835.30; my $b = -21715.90; my $c = 9652.20; my $d = -9771.60; sub to2dp { sprintf "%.2f", $_[0] + 1e-8 } print ("total = $total\n"); print "to2dp = ", to2dp($total), "\n"; $total += $a; print ("total = $total\n"); print "to2dp = ", to2dp($total), "\n"; $total += $b; print ("total = $total\n"); print "to2dp = ", to2dp($total), "\n"; $total += $c; print ("total = $total\n"); print "to2dp = ", to2dp($total), "\n"; $total += $d; print ("total = $total\n"); print "to2dp = ", to2dp($total), "\n"; $total = sprintf("%.2f", $total); print ("total = $total\n"); print "to2dp = ", to2dp($total), "\n"; This produces the output: total = 0 to2dp = 0.00 total = 21835.3 to2dp = 21835.30 total = 119.399999999998 to2dp = 119.40 total = 9771.6 to2dp = 9771.60 total = -1.81898940354586e-12 to2dp = 0.00 total = -0.00 to2dp = 0.00 When you want to compare floating point numbers, check that their difference is less than some appropriately small delta: $delta = 1e-8; if (abs($a - $b) < $delta) # numbers are "equal" But ideally do it all in integers or use a special purpose library if you need a greater range. If you use floating point then ensure you know its limits. -- Paul Johnson - p...@pjcj.net http://www.pjcj.net -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/