in reply to precision problem ?
A classical example:
$ perl -le 'print "Wrong " if 19.08 + 2.01 != 21.09;' Wrong
You would most probably get the same type of result with Python, Ruby, C, Java, Fortran or what have you. The problem is not Perl, but the architecture of almost all current computers. The problem has to do with differences between numbers (the mathematical concept) and numerals (their representation on a computer). Just as 1/3 has a never ending 0.333333... representation in decimal notation, some numbers deemed to be simple in decimal notation have a never ending representation in the internal binary format of most computers.
To find out the difference between 19.08 + 2.01 and 21.09, try this:
$ perl -le 'print 21.09 - (19.08 + 2.01), "\n";' 3.5527136788005e-15
3.5527136788005e-15 is admitedly a very small number, but it is not 0. The classical method for comparing floating point notation numbers is to check if the absolute value of their difference is smaller than a very small number usually called epsilon (perhaps something like 1e-14). If the difference is smaller than epsilon, then the number are considered to be the same. For example:
$ perl -le '$epsilon = 1e-14; print "Wrong " if abs (19.08 + 2.01 - 21 +.09) > $epsilon;' $ perl -le '$epsilon = 1e-14; print "Wrong " if abs (19.08 + 2.02 - 21 +.09) > $epsilon;' Wrong
In the first case, the difference is about 3e-15, so smaller than epsilon, I do not get an error; in the second case, the difference is about 0.01, much larger that epsilon, I get the "wrong" message.
To tell the truth, there is another source of errors, which is perhaps more important in your case: the summation of rounding errors. A very classical problem: make an invoice of a few lines, with the tax free amount in the first column, and the tax-included amount in the second comumn, for a few items. Then calculate the total tax free amount, apply the common tax rate to that total mount, chances are high that the total tax-included amount calculated this way will not be the same as the sum of the tax-included items. The company for which I am a consultant spent several hundred thousand euros on an IT project to try to get rid of these rounding errors (making all calculations with 5 decimal digits), the situation is now much better, but you just can't get rid of all discrepancies, so that the invoice has a sentence somewhere saying that the tax amount for individual lines are only given as an estimate, only the last total line contains real amounts.
BTW, using the bigint module seems to solve the problem:
$ perl -le 'use bigint; print "Wrong " if 19.08 + 2.01 != 21.09;' $ perl -le 'use bigint; print 21.09 - (19.08 + 2.01), "\n";' 0
I am not sure, though, that this works in all cases.
Update: Oops, thanks choroba, the above (crossed part) is obviously silly. Yes, bignum should probably help much better. But I haven't tested yet.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: precision problem ?
by choroba (Cardinal) on Aug 07, 2013 at 21:28 UTC | |
by Laurent_R (Canon) on Aug 07, 2013 at 21:54 UTC |