Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: How to compare floating numbers

I wrote the following Perl script. However, it does not print "1". I did some research and it seems it is because of the IEEE representation of floating-point number. So, is there a better way to compare floating-point numbers in Perl?

for (my $tmp = 0.1; $tmp <= 1; $tmp+=0.05){print $tmp."\n"}

Output:

0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
0.55
0.6
0.65
0.7
0.75
0.8
0.85
0.9
0.95
like image 642
Bin Zhou Avatar asked Feb 05 '14 20:02

Bin Zhou


People also ask

How do you compare floating numbers?

To compare two floating point values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

Can we compare int with float?

Here in this code, we can see that if we pass an integer value to a float then it will act as an integer and returns an integer value as output. But the max values for both of them come to be different.

Why do we never use == to compare floating point numbers?

Because floating point arithmetic is different from real number arithmetic. Bottom line: Never use == to compare two floating point numbers. Here's a simple example: double x = 1.0 / 10.0; double y = x * 10.0; if (y !=

Can float and double compare?

double has 2x more precision than float. float is a 32-bit IEEE 754 single precision Floating Point Number – 1 bit for the sign, 8 bits for the exponent, and 23* for the value. float has 7 decimal digits of precision.


2 Answers

All computations that use floating point numbers may have precision errors, and if you reuse the results, those precision erros stack up. One thing to learn from that is to never use a float as a loop control variable.

Use something like

for (my $tmp=2; $tmp<=20; tmp++) {
    print $tmp/20.0, "\n";
}

whereever you can. If you really really need to compare two floats ($a, $b) something like

if (abs($a - $b) < 0.000001)

is the only thing that really works -- however, this might have issues as well depending on how small the difference can be to count as a real difference.

like image 80
Guntram Blohm Avatar answered Sep 27 '22 21:09

Guntram Blohm


Multiply everything so that you work only with integers - in this case 100.

Then when you print the number, divide it by that same number;

for (my $tmp = 10; $tmp <= 100; $tmp+=5){print $tmp/100 ."\n"}

Gives me:

0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
0.55
0.6
0.65
0.7
0.75
0.8
0.85
0.9
0.95
1
like image 32
Andrejovich Avatar answered Sep 27 '22 22:09

Andrejovich