SPUG: Incorrect subtraction result

Adam Monsen haircut at gmail.com
Tue Aug 26 06:31:54 PDT 2008


On Tue, Aug 26, 2008 at 4:50 AM, Mike Schuh <schuh at farmdale.com> wrote:
> Solutions: Use integer pennies, dividing by 100 when displaying the values
> as dollars (and use the integer pragma).

Agreed.

At a substantial performance penalty you can also try using /more/
floating point precision. There are some CPAN modules worth examining
like Math::Currency and Math::BigFloat.

For example; before:

#!/usr/bin/perl -w
use strict;
my $a = 1.0;      # one dollar
my $b = $a - 0.9; # minus 90 cents
$b    = $b - 0.1; # minus 10 cents
print "$b\n";     # prints -2.77555756156289e-17

after:

#!/usr/bin/perl -w
use strict;
use Math::BigFloat;
my $a = Math::BigFloat->new(1.0); # one dollar
my $b = $a - 0.9; # minus 90 cents
$b    = $b - 0.1; # minus 10 cents
print "$b\n";     # prints 0

Even if you can't use CPAN modules (since this is for a class) reading
their code might be helpful in trying to roll your own money-ish type.

Floating point math is one of the tricky, interesting parts of binary
arithmetic that programmers must learn in order to become engineers.
You'll encounter this in any programming language you use.

quick answer from perlfaq4:
  http://tinyurl.com/5hecdh

more on floating point:
  http://tinyurl.com/6k4emc

read this too! (mentioned by Ben Reser in this thread):
  http://tinyurl.com/6fzwrc

Nice work on the code. Some tips:
* "use strict;" in your module
* don't hardcode class name in new() method, one of the arguments to
new() is the class name
* generally you wouldn't print stuff from within your module... try to
separate the core logic of your module from the presentation to the
user

-- 
Adam Monsen


More information about the spug-list mailing list