Comparing Floating-Point Numbers
Problem
Floating-point arithmetic isn’t precise. You want to compare two floating-point numbers and know if they’re equal when carried out to a certain number of decimal places. Most of the time, this is the way you should compare floating-point numbers for equality.
Solution
Use sprintf to format the numbers to a certain
number of decimal places, then compare the resulting strings:
# equal(NUM1, NUM2, ACCURACY) : returns true if NUM1 and NUM2 are
# equal to ACCURACY number of decimal places
sub equal {
my ($A, $B, $dp) = @_;
return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
}Alternatively, store the numbers as integers by assuming the decimal place.
Discussion
You need the equal routine because most
computers’ floating-point representations aren’t
accurate. See the Introduction for a discussion of this issue.
If you have a fixed number of decimal places, as with currency, you
can sidestep the problem by storing your values as integers. Storing
$3.50 as 350 instead of
3.5 removes the need for floating-point values.
Reintroduce the decimal point on output:
$wage = 536; # $5.36/hour
$week = 40 * $wage; # $214.40
printf("One week's wage is: \$%.2f\n", $week/100);
One week's wage is: $214.40It rarely makes sense to compare to more than 15 decimal places.
See Also
The sprintf function in perlfunc
(1) and Chapter 3 of Programming Perl
; the entry on $# in the
perlvar(1) manpage and Chapter 2 of
Programming Perl; the documentation for the standard Math::BigFloat ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access