-1

I am running a perl script and basic addition operators seem to be not working. For my code

print $total_charges," 1 \n";
print $payments," payments\n";
$total_charges+=$payments;
print $total_charges," 2 \n";

For this code, the output is the following

10192.19 1
-401.99 payments
9790.20000000005 2

If you do the math, this number would be correct except for the extra decimal places. What is going on?

I need these numbers to be accurate. Any suggestions on fixing this, or do I just truncate to 2 decimals each time?

mrfish
  • 64
  • 7
  • 4
    See: http://stackoverflow.com/questions/588004/is-floating-point-math-broken – AKHolland Mar 25 '15 at 20:19
  • Thanks for the input. Is there a good perl workaround? – mrfish Mar 25 '15 at 20:23
  • 1
    You could format your output to the required number of decimal places using [sprintf](http://perldoc.perl.org/functions/sprintf.html) / [printf](http://perldoc.perl.org/functions/printf.html) – Grant McLean Mar 25 '15 at 20:26
  • 4
    This is why you don't deal with money as floating point numbers. Represent $14.99 as integer value 1499. – Andy Lester Mar 25 '15 at 20:33
  • 1
    @AndyLester Although I think the "why" in this question is a dup, the "how can I fix it?" part isn't addressed in the post I linked. Considering the potential repercussions of using floats in financial applications, your comment would make a great answer. – ThisSuitIsBlackNot Mar 25 '15 at 20:39

1 Answers1

2

This is why you don't deal with money as floating point numbers. Represent $14.99 as integer value 1499. Divide by 100 only at the time when you want to display, as in:

my $price = 1499;
printf( "You pay only %.2f", $price/100 );
Andy Lester
  • 91,102
  • 13
  • 100
  • 152
  • Yeah, I have been pondering this. My program has to interface with several outside sources, all using the traditional currency format. I have to decide whether it is worth it to translate all these numbers as they come in. – mrfish Mar 25 '15 at 21:12
  • 2
    You can used fixed decimal if your database allows it. For instance, you can declare a column to be `DECIMAL(10,2)` and it will have exactly two decimal places. https://dev.mysql.com/doc/refman/5.0/en/fixed-point-types.html – Andy Lester Mar 25 '15 at 21:15