Re: Comparing results of math operations
by Laurent_R (Canon) on Apr 16, 2014 at 09:26 UTC

This is a usual difficulty with floating point number arithmetics (with most languages). In your first example, try this:
my $x = 0.95*806;
my $y = 1.3*589;
print $y  $x; # prints something like : 1.13686837721616e13
So, although the numbers seem to be equal when rounded to 1 or even 5 decimal places, they are not really equal. Even if the numbers were mathematically exactly equal, the simple fact that you derived them from arithmetical operations on other source floating point numbers may lead to different results, because the original numbers are first converted to an internal binary representation which may lead to some internal rounding even before the multiplication is applied.
The lesson is: don't compare for equality floating point numbers derived from arithmetic operations; rather subtract one from the other and check if the absolute value of the difference is smaller than a certain predetermined very small number.
 [reply] [d/l] 
Re: Comparing results of math operations
by zentara (Archbishop) on Apr 16, 2014 at 09:50 UTC

Here is another textbook example which demonstrates the problem. You need to specify how many digits of accuracy you need for the comparison, and round your floats off accordingly.
#!/usr/bin/perl w
use strict;
my ( $number, $premium, $expected );
$number = 1.80;
$premium = $number * ( 1 + 10/100 ); # 1.8 + 10% of 1.8
$expected = 1.98; # As we know 1.8 + 10% of 1.8 is 1.98
printf "Number 1 : %20.19f\n", $premium ;
printf "Number 2 : %20.19f\n", $expected ;
print "Not" if ( $expected != $premium );
print "Equal !! ";
__END__
Number 1 : 1.9800000000000002043
Number 2 : 1.9799999999999999822
NotEqual !!
 [reply] [d/l] 
Re: Comparing results of math operations (try integer)
by LanX (Bishop) on Apr 16, 2014 at 09:55 UTC

DB<107> $x=95*806 /100;
=> "765.7"
DB<108> $y=13*589 /10;
=> "765.7"
DB<109> $x <=> $y
=> 0
So just calculate with integers and shift the decimal point afterwards!
The deeper reason for this mess is that Humans have too many fingers ;)
Cheers Rolf
( addicted to the Perl Programming Language)
 [reply] [d/l] 
Re: Comparing results of math operations
by hippo (Abbot) on Apr 16, 2014 at 10:30 UTC

This and all the usual resulting questions are explained very well in the Numbers section of the FAQ. I would strongly advise you to read all the way through that section if computing with floating point numbers is new to you (which it would appear to be). Good luck.
 [reply] 
Re: Comparing results of math operations
by syphilis (Chancellor) on Apr 16, 2014 at 12:43 UTC

Hi,
The essential difference between the first assignments to $x and $y, and the assignments made later (in the "#now with simpler math" section) is that while 2, 1.25, 5, and 0.5 can *all* be represented exactly in base 2, the same cannot be said of 0.95, 806, 1.3 and 589.
Sure ... both 806 and 589 can be represented exactly in base 2, but 0.95 and 1.3 cannot.
Hence the first calculations do not yield "expected" values, whereas the second calculations *do* yield expected values.
Workarounds include doing base 10 calculations  eg by using Math::Decimal (pure perl) or Math::Decimal64 (XS access to the C compiler's _Decimal64 arithmetic).
Cheers, Rob  [reply] 

I agree that the transformation from decimal to binary fractions is the biggest source of problems.
But does switching to decimal floats solve all problems?
1/3 can't be represented lossfree in neither decimal nor binary floats (3 is not a primefactor of 10 or 2)
So (1/3 * 3) can be different to 1.
Though it isn't ATM
DB<125> 1/3 *3 <=> 1
=> 0
I'm not sure if that's always the case for similar calculations.
I remember similar discussions talking about something like "symbolic calculations", where divisor and denominator are kept separate till the end.
Cheers Rolf
( addicted to the Perl Programming Language)
 [reply] [d/l] 

But does switching to decimal floats solve all problems?
No ... but then rational arithmetic (where you keep divisor and numerator separate) also fails to solve all problems, as it falls down when you start to deal with irrational numbers such as sqrt(2) or transcendentals such as pi.
I think what drew me to decimal arithmetic was that the values that appeared in the OP's post were all *exactly* representable in base 10, as were the results of the calculations he presented.
If there had been a "1 / 3" (or some other rational value that couldn't be exactly represented in base 10) in that post then I would more likely have been drawn to modules such as Math::BigRat or Math::GMPq.
Cheers, Rob
 [reply] 

discussions talking about something like "symbolic calculations", where divisor and denominator are kept separate till the end
Do you mean Math::Fraction?
 [reply] 

Re: Comparing results of math operations
by AnomalousMonk (Chancellor) on Apr 16, 2014 at 13:43 UTC

 [reply] 

 [reply] 
Re: Comparing results of math operations
by Anonymous Monk on Apr 16, 2014 at 12:11 UTC

Floatingpoint number like little pile of sand on the ground. Each time you pick it up and move it around, you lose a little sand (precision) and pick up a little dirt (error). Rounding and such masks this effect but does not get rid of it. Add up enough numbers and you will see (to the vexation of your accountant) that the total at the bottom is "off by a few cents." In fact, the total is correct, because it is the sum of nonrounded numbers, whereas the check performed by the calculatortoting accountant is the sum of rounded numbers.  [reply] 
Re: Comparing results of math operations
by Anonymous Monk on Apr 17, 2014 at 07:59 UTC

The 0.95 * 806, 1.3 * 589 example; gives me
765.699999999999932
765.700000000000045
when I use the 10digit calculator trick of subtracting off the leading digits and multiplying by 10, to see the hidden digit off to the right.  [reply] [d/l] 