Decimal equality question

A

a

this is probably a dumb question, but i'm not seeing why perl is treating
these numbers as unequal. i've tried on a few different machines (intel and
sparc) and perl versions (5.8.7, 5.8.3) and get the same result.

perl -e 'if (361.35 == (72.27*5)) { print "EQUAL"; } else {print "NOT EQUAL";}'
 
P

Paul Lalli

a said:
this is probably a dumb question, but i'm not seeing why perl is treating
these numbers as unequal. i've tried on a few different machines (intel and
sparc) and perl versions (5.8.7, 5.8.3) and get the same result.

perl -e 'if (361.35 == (72.27*5)) { print "EQUAL"; } else {print "NOT EQUAL";}'

$ perl -le' print 361.35 - (72.27 * 5)'
5.6843418860808e-14

It has nothing to do with Perl. This is a fundamental property of
numerical computing. Certain (most) decimals can not be expressed
exactly in base 2.

As a general rule, never test floating points for numeric equality.
Either test for equality plus or minus a small epsilon, or multiply by
an appropriate factor and convert to integers, and compare those:

$ perl -le' $x = 72.27 * 5; $e = .00001; print ($x + $e > 361.35 and
$x - $e < 361.35 ? "Equal" : "Not Equal")'
Equal

or

$ perl -le' $x = 72.27 * 5; $x = int($x * 100); print ($x == 36135 ?
"Equal" : "Not Equal")'
Equal


See also perldoc -q 999

Paul Lalli
 
P

Paul Lalli

Paul said:
$ perl -le' $x = 72.27 * 5; $e = .00001; print ($x + $e > 361.35 and
$x - $e < 361.35 ? "Equal" : "Not Equal")'
Equal

More traditionally, this is written:

$ perl -le' $x = 72.27 * 5; print (abs($x - 361.35) < .00001 ? "Equal"
: "Not Equal")'
Equal

I'm not enitirely sure why I didn't type that to begin with...

Paul Lalli
 
X

X

i guess it\'s been awhile since my last computer science course... but i\'m
still embarrassed. thanks for the answer..greatly appreciated.
 
R

robic0

$ perl -le' print 361.35 - (72.27 * 5)'
5.6843418860808e-14

It has nothing to do with Perl. This is a fundamental property of
numerical computing. Certain (most) decimals can not be expressed
exactly in base 2.

As a general rule, never test floating points for numeric equality.
Either test for equality plus or minus a small epsilon, or multiply by
an appropriate factor and convert to integers, and compare those:

$ perl -le' $x = 72.27 * 5; $e = .00001; print ($x + $e > 361.35 and
$x - $e < 361.35 ? "Equal" : "Not Equal")'
Equal
This is good advice since .00001, in metric is a micron. In Metrology
..000001, a tenth of a micron is the best measurement optically,
with microscope optics. However, i'm sure all calculations should be done
with doubles and not floats. Course thats not something that you have
control of in Perl. But i'm sure doubles are used.
 
D

DJ Stunks

robic0 said:
This is good advice since .00001, in metric is a micron. In Metrology
.000001, a tenth of a micron is the best measurement optically,
with microscope optics. However, i'm sure all calculations should be done
with doubles and not floats. Course thats not something that you have
control of in Perl. But i'm sure doubles are used.

lmfao

stop it, my sides hurt.
 
J

Jürgen Exner

a said:
this is probably a dumb question, but i'm not seeing why perl is
treating these numbers as unequal. i've tried on a few different
machines (intel and sparc) and perl versions (5.8.7, 5.8.3) and get
the same result.

perl -e 'if (361.35 == (72.27*5)) { print "EQUAL"; } else {print "NOT
EQUAL";}'

First commandment of computer numerics:

"Thou shalt not use equality on floating point numbers."

For details see "perldoc -q 999" and/or the numerous previous articles on
this topic.

jue
 
R

robic0

This is good advice since .00001, in metric is a micron. In Metrology
.000001, a tenth of a micron is the best measurement optically,
with microscope optics. However, i'm sure all calculations should be done
with doubles and not floats. Course thats not something that you have
control of in Perl. But i'm sure doubles are used.

Equality is never checked for in float/doubles of course, but Lalli's
..00001 to dislodge fence setters is widely used in Engineering and
especially Metrology as a defacto standard in positional comparisions.
I did optics measurement and stage coordinate systems for a few years.
 
R

robic0

Equality is never checked for in float/doubles of course, but Lalli's
.00001 to dislodge fence setters is widely used in Engineering and
especially Metrology as a defacto standard in positional comparisions.
I did optics measurement and stage coordinate systems for a few years.

As a followup, consider that nothing is relavent past what can be
physically measured in real life... notwithstanding the electron microscope.
 
A

Anno Siegel

a said:
this is probably a dumb question, but i'm not seeing why perl is treating
these numbers as unequal. i've tried on a few different machines (intel and
sparc) and perl versions (5.8.7, 5.8.3) and get the same result.

perl -e 'if (361.35 == (72.27*5)) { print "EQUAL"; } else {print "NOT EQUAL";}'

The diagnosis (limited accuracy) and cure (use an epsilon in comparison)
have been given elsewhere in this thread.

Instead of explicitly choosing an epsilon, you can use Perl's internal
rounding to trim off extra precision:

perl -e 'if (361.35 eq (72.27*5)) { print "EQUAL"; } else {print "NOT EQUAL"'

That prints "EQUAL".

Using string comparison on the numbers effectively rounds the numbers
to an implementation-dependent number of places. In effect, you are
comparing with an epsilon of 0.5 times the least significant digit.

"When they print the same, they are the same"

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,517
Latest member
Andres38A1

Latest Threads

Top