Velocity Reviews > Perl > comparing floating point numbers

# comparing floating point numbers

Thens
Guest
Posts: n/a

 07-10-2003
Hi,

I have a problem comparing floating point numbers. After a lot of googling and docs I found the issue to be because of the internal floating point representation.

Here is a sample program that explains that

#!/usr/local/bin/perl

use strict;
use warnings;

my ( \$num, \$num1, \$num2 );

\$num = 1.8;
\$num1 = ( \$num * (1 + (10/100) ) ); # \$num + 10% \$num => 1.98

print "Number :", sprintf "%2.20f \n" , \$num;
print "Number +10% :", sprintf "%2.20f \n", \$num1;

\$num2 = 1.98;
print "Number +10% :", sprintf "%30.20f \n", \$num2;

if ( \$num1 != \$num2 ) {
print "FIRST PASS >> \$num1 is not equal to \$num2 !! \n";
}
if ( (\$num1+0.1) != (\$num2+.1) ) {
print "SECOND PASS >> \$num1 is not eqaul to \$num2 !!\n";
}

This prints

FIRST PASS >> 1.98 is not equal to 1.98 !!

I understand this is because of the floating point representation. Then I tried to solve it by adding 0.1 at both the ends and then comparing the numbers. THis seems to have solved the problem. My question is, Is this a reliable solution.

While searching the group archive, I found this can be achieved by checking for a small delta like

\$delta = 0.0001

if ( abs ( \$num1 - \$num2 ) < \$delta ) {
# Now they are eual
}
...

I wanted to know under what circumstances may adding 0.1 at both ends can fail.

Thanks and Regards,
Thens.

Mothra
Guest
Posts: n/a

 07-10-2003

"Thens" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi,
>
> I have a problem comparing floating point numbers. After a lot of

googling and docs I found the issue to be because of the internal floating
point representation.
>

[snipped]

Here is what I use to compare two floating numbers.

until ( equal( \$tmp_rise_2, \$tmp_rise_3, 8 ) ) {
do stuff....
}

sub equal {

#
#
# FUNCTIONAL SEQUENCE for equal
#
# _GIVEN
#
# Two floating point numbers and Accuracy
#
# _THEN
#
# Use sprintf to format the numbers to Accuracy
# number of decimal places
#
# _RETURN
#
# True if the numbers are equal
#
my ( \$A, \$B, \$dp ) = @_;

return sprintf( "%.\${dp}g", \$A ) eq sprintf( "%.\${dp}g", \$B );
}

hope this helps

Mothra

Greg Bacon
Guest
Posts: n/a

 07-10-2003
In article <(E-Mail Removed)>,
Thens <(E-Mail Removed)> wrote:

: [...]
:
: While searching the group archive, I found this can be achieved by
: checking for a small delta like
:
: \$delta = 0.0001
:
: if ( abs ( \$num1 - \$num2 ) < \$delta ) {
: # Now they are eual
: }
:
: I wanted to know under what circumstances may adding 0.1 at both
: ends can fail.

That depends on the nature of your computation. Remember that computers
use finite-precision arithmetic, the way you structure computations can
hurt you, e.g., dividing by a very small number or subtracting numbers
close values can produce serious rounding errors.

See "What Every Computer Scientist Should Know About Floating-Point
Arithmetic" at

http://docs.sun.com/source/806-3568/ncg_goldberg.html

Even checking for membership in some epsilon-neighborhood isn't
always sufficient:

Incidentally, some people think that the solution to such
anomalies is never to compare floating-point numbers for
equality, but instead to consider them equal if they are within
some error bound E. This is hardly a cure-all because it raises
as many questions as it answers. What should the value of E be?
If x < 0 and y > 0 are within E, should they really be
considered to be equal, even though they have different signs?
Furthermore, the relation defined by this rule,

a ~ b <=> |a - b| < E

is not an equivalence relation because a ~ b and b ~ c does
not imply that a ~ c.

ibid.

Greg
--
While the federal government is frustrating when it treats economic
problems with nonchalance, it is terrifying when it gets involved.
-- Bob Novak

Michael P. Broida
Guest
Posts: n/a

 07-10-2003
Thens wrote:
>
> Hi,
>
> I have a problem comparing floating point numbers.

One of the things you need to learn about floating point
numbers is:
NEVER compare them for equality (or inequality).

Mike