B
bill
I just recently came across this snippet:
my $EPSILON = 1;
$EPSILON /= 2 while 0.5 + $EPSILON/2 > 0.5;
where $EPSILON was later used, e.g., to compare floats for equality:
sub float_equal {
my ($x, $y) = @_;
return !($x||$y) || ($x+$y) && abs(($x-$y)/($x+$y)) < $EPSILON;
}
(The above is the gist of what I recall, not verbatim production
code, but I think I got it right.)
I'm not very knowledgeable about numerics, so I was wondering
whether this was the best way to compare floats for equality.
I thought that this would be a FAQ, but I couldn't find it.
The first edition of The Perl Cookbook recommends converting both
numbers to the same string format, and then doing a string comparison:
sub equal {
my ($A, $B, $dp) = @_;
return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
}
The main reason I don't like this approach is that, in my experience,
some numerical objects, such as Math::BigFloat and Math:ari,
don't work well with sprintf.
Also, I recall that in C there are pre-defined constants (e.g.
DBL_EPSILON in limits.h) that can be used for this kind of tests.
Is there something similar in Perl?
Many thanks in advance!
bill
P.S. If someone in Perl publishing reads this: a book on Perl
numerics is sorely needed (fundamentals, algorithms, recipes, best
practices) is sorely needed.
my $EPSILON = 1;
$EPSILON /= 2 while 0.5 + $EPSILON/2 > 0.5;
where $EPSILON was later used, e.g., to compare floats for equality:
sub float_equal {
my ($x, $y) = @_;
return !($x||$y) || ($x+$y) && abs(($x-$y)/($x+$y)) < $EPSILON;
}
(The above is the gist of what I recall, not verbatim production
code, but I think I got it right.)
I'm not very knowledgeable about numerics, so I was wondering
whether this was the best way to compare floats for equality.
I thought that this would be a FAQ, but I couldn't find it.
The first edition of The Perl Cookbook recommends converting both
numbers to the same string format, and then doing a string comparison:
sub equal {
my ($A, $B, $dp) = @_;
return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
}
The main reason I don't like this approach is that, in my experience,
some numerical objects, such as Math::BigFloat and Math:ari,
don't work well with sprintf.
Also, I recall that in C there are pre-defined constants (e.g.
DBL_EPSILON in limits.h) that can be used for this kind of tests.
Is there something similar in Perl?
Many thanks in advance!
bill
P.S. If someone in Perl publishing reads this: a book on Perl
numerics is sorely needed (fundamentals, algorithms, recipes, best
practices) is sorely needed.