test for equality not working 8.0.0.783 (R2012b)

I encountered a weird issue when I was trying for test of equality in two array (eq function). I tried to reproduced it as below. Does anybody know what is going on? I have searched for it online but couldn't find a proper solution. I know it is a precision problem, but for test of equality one thinks it should at least work properly without worrying about these type of issues. My OS is OSX 10.8. A colleague of mine reproduced it in MATLAB 2011a (OS: Linux) as well.
>> A = 0.05:0.05:0.3
A =
0.050000000000000 0.100000000000000 0.150000000000000 0.200000000000000 0.250000000000000 0.300000000000000
>> A==0.15
ans =
0 0 0 0 0 0
>> A==(0.05+0.1)
ans =
0 0 1 0 0 0
>> (A(3)-0.15)*1e16
ans =
0.277555756156289
UPDATE (unique function is not working either):
>> unique([A, 0.15])
ans =
0.050000000000000 0.100000000000000 0.150000000000000 0.150000000000000 0.200000000000000 0.250000000000000 0.300000000000000

 Accepted Answer

This is the well-known and often responded to in this forum (and others) problem of trying to compare floating point numbers.
This is not unique to MATLAB
In R, the same thing happens:
> x <-seq(0.05,0.3,by = 0.05);
> x == 0.15
[1] FALSE FALSE FALSE FALSE FALSE FALSE
In Python too:
>>> import numpy as np
>>> test = np.linspace(0.05,.3,6);
>>> test == 0.15
array([False, False, False, False, False, False], dtype=bool)

2 Comments

Indeed. I tried it in R as well and it doesn't work only for 0.15. It works ,however, for other array elements (0.05, 0.1, 0.2, 0.25, 0.3). When it comes to floating point comparison, I think I should give up and use exact comparison. But I thought maybe there is a way around it that I am not aware of.
yes, use a tolerance.
abs((x-0.15))< tol
For example:
tol = 1e-10;
abs((A-0.15)) < tol

Sign in to comment.

More Answers (1)

Actually, for the test of equality, you should check for exact equality, and you should control the tolerance you are willing to accept.
cmp = abs(A(3)-0.15) < 5*eps(A(3))
Unique does what it says on the tin - it DOES work.

4 Comments

If it REALLY does what it says on the tin, it should work for all cases. It doesn't really seem to be consistent.
>> unique([A, 0.15])
ans =
5.0000e-02 1.0000e-01 1.5000e-01 1.5000e-01 2.0000e-01 2.5000e-01 3.0000e-01
>> unique([A, 0.2])
ans =
5.0000e-02 1.0000e-01 1.5000e-01 2.0000e-01 2.0000e-01 2.5000e-01 3.0000e-01
>> unique([A, 0.3])
ans =
5.0000e-02 1.0000e-01 1.5000e-01 2.0000e-01 2.5000e-01 3.0000e-01
>> unique([A, 0.05])
ans =
5.0000e-02 1.0000e-01 1.5000e-01 2.0000e-01 2.5000e-01 3.0000e-01
It does what it says on the tin, but it doesn't do what you think it should.
What should unique(1-[0:eps(1):10*eps(1)]) output?
Should it output each value because, no matter how small the difference, they are different, or should it output 1, because the difference is really small?
@Hassan,
Try this. At the command line, type:
format hex
And now inspect A and 0.15, e.g.
>> A = 0.05:0.05:0.3
A =
3fa999999999999a 3fb999999999999a 3fc3333333333334 3fc9999999999999 3fd0000000000000 3fd3333333333333
>> 0.15
ans =
3fc3333333333333
This formatting displays the hexadecimal representation of each number, which is how Matlab internally stores each distinct value. Notably, since there is a finite number of bits that can be stored for each number (64 for a double), each number can be separated by another number by no less than one hexadecimal digit (which corresponds to one computer bit). Note that the hex representation of 0.15, which is 3fc3333333333333, is NOT contained exactly in the hex representation of A-- the last digit '3' does not match. This is why unique() is picking up both--internally, Matlab considers them distinct values.
@Iain: Thanks that can indeed solve the issue.
@Matt: It is interesting to see it in this format. So do you what is it that only 0.2 and 0.15 are stored differently? When I try 0.05:0.05:0.15 I get different result than what I get for 0.05:0.05:0.3. I mean the value for 0.15 is stored differently. Why is it like this?
>> 0.05:0.05:0.15
ans =
3fa999999999999a 3fb999999999999a 3fc3333333333333
>> 0.15
ans =
3fc3333333333333
the value for 0.15 is same in this case, but not in my initial question.

Sign in to comment.

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!