0
Аяқталған

Error for boolean operation at certain precision

Michael_ 7 year бұрын updated by Pavel Holoborodko 7 year бұрын 3

Hello Pavel.

I got the following problem:

mp.Digits(349);
array=mp('2')*mp('10')^mp('-4'):mp('2')*mp('10')^mp('-4'):mp('1');
array(1,100)==mp('0.02')

ans =
logical
1

mp.Digits(350);
array=mp('2')*mp('10')^mp('-4'):mp('2')*mp('10')^mp('-4'):mp('1');
array(1,100)==mp('0.02')

ans =
logical
0

mp.Digits(351);
array=mp('2')*mp('10')^mp('-4'):mp('2')*mp('10')^mp('-4'):mp('1');
array(1,100)==mp('0.02')
ans =
logical
1


This apperas quite randomly, deppending on the used precision. You can try for example mp.Digits(352) to mp.Digits(355).


Thank you for your help.

Аяқталған

Dear Michael,


Thank you for question and sorry for delay in reply.


This situation is not a bug.

Toolbox follows philosophy of IEEE standard and stores numbers in binary floating-point format.

The thing is that number 0.02 is not exactly representable in binary floating-point format regardless of precision.


We can only approximate it by the nearest representable number in given precision, for example (I use 15 digits for simplicity):


>> mp.Digits(15);
>> fprintf('%.20e\n',mp('0.02'))
1.99999999999999900080e-02

Colon operation includes quite a lot of algorithms under the hood (e.g. to make sure that generated numbers are symmetric around midpoint, etc.) - and there is no guarantee that it will generate exactly the same bit-to-bit approximation to 0.02 in the middle of generated sequence:


>> array=mp('2*10^(-4)'):mp('2*10^(-4)'):mp('1');
>> fprintf('%.20e\n',array(1,100))
2.00000000000000177636e-02

Both numbers are accurate approximations to 0.02 up to the same number of decimal digits:

>> fprintf('%.14e\n',mp('0.02'))
2.00000000000000e-02
>> fprintf('%.14e\n',array(1,100))
2.00000000000000e-02

But they are not the same in bit-to-bit binary representation (they might be in some precisions, but there is no guarantee, of course)!


This is classical issue of decimal vs. binary floating-point numbers. And this is the reason why == shouldn't be used in floating-point world. Please compare numbers by some tolerance instead.


Would it be Ok to make this question public, since it touches common issue and can be useful for others?

Thank you for your answer.
I understand the problem, but it seems to me that it never had the problem in Matlab double-precision. Maybe the implemented some tolerance in the "==" operator. You can make the question public if you want. :)

I am sure there is no tolerance behind the "==".

This rather relates to algorithms in colon - TMW developers change it from version to version and there is a chance that 0.02 coincides with array(1,100) in this particular implementation of colon.


Anyway, surprisingly colon is very difficult to implement correctly and TMW support forum has a lot of examples of some degenerate cases, e.g. see comments on this post:

http://blogs.mathworks.com/loren/2006/11/10/all-about-the-colon-operator/