MATLAB: Ismembertol – inconsistent results compared to documentation

ismembertolprecision

Hello,
Let me first start by quoting MATLAB documentation on the function ismembertol found here: http://www.mathworks.com/help/matlab/ref/ismembertol.html
My question is specific to the following section of the documentation:
Specify Absolute Tolerance
By default, ismembertol uses a tolerance test of the form abs(u-v) <= tol*DS, where DS automatically scales based on the magnitude of the input data. You can specify a different DS value to use with the DataScale option. However, absolute tolerances (where DS is a scalar) do not scale based on the magnitude of the input data.
First, compare two small values that are a distance eps apart. Specify tol and DS to make the within tolerance equation abs(u-v) <= 10^-6.
x = 0.1;
ismembertol(x, exp(log(x)), 10^-6, 'DataScale', 1)
ans =
1
So by the above example in the documentation, ismembertol will place a non-strict inequality for the tolerance. However, I am seeing that it is placing strict inequality when I run it on my MATLAB R2015a. Here is a simple example where I noticed it:
x = 3.8557;
y = 3.8556;
tol = 0.0001;
DS = 1;
since abs(x-y) is 0.0001, which is equal to tol*DS = 0.0001, abs(x-y)<=tol*DS is satisfied, so x should be a member of y, therefore I expect the answer to be 1.
But this is what I get:
ismembertol(x, y, tol, 'DataScale', DS)
ans =
0
However, when I increase tolerance by a tiny bit,
tol = 0.00011
ismembertol(x, y, tol, 'DataScale', DS)
ans =
1
Now it indicates that x is a member of y.
This is very confusing to me… is this a precision issue where abs(x-y) and tol are both 0.0001 yet MATLAB can't recognize that they are equal?
Any help will be greatly appreciated! Thanks in advance,

Best Answer

ismembertol is not doing anything wrong.
The problem is that you think that those values are different by 0.0001, but in reality they are not.
You are getting confused by the limited precision of floating point numbers. Nose of those values can be represented exactly using floating point numbers, so what you see is an approximation of the real values stored by your computer. Try this:
>> sprintf('%.30f',0.0001)
ans =
0.000100000000000000000000000000
>> sprintf('%.30f',3.8557-3.8556)
ans =
0.000100000000000211030000000000
For an even better representation of floating point values, use this FEX submission:
And because this is a topic that confuses many beginners there are many pages on this forum explaining floating point numbers: