if and sum not working together
3 views (last 30 days)
I have come across a rather weird problem. When I calculate the sum of an array that I know is going to be e.g. 0.01, the if statement will not recognize it as such.
I am not that good in explaining, so here is a simple code:
a = zeros(10,1)+0.001;
b = sum(a)
if b ~= 0.01
c = 1
c = 0
Obviously the output should be: "b = 0.01 c = 0". But that's not what I'm getting. Instead I get a "c = 1".
Why does this happen?
More Answers (2)
Steven Lord on 23 Sep 2022
Please try this little experiment. Find something to write with and something to write on (ideally compatible things; pencil and paper not pencil and whiteboard.)
Step 1: Using long division (like you learned in school) divide 1 by 3. Call the result x. You are allowed to write as many decimal places of the result as you want, but only those you explicitly write can be used in step 2. No using 0.3 repeating to get "an infinite" number of places.
Step 2: Multiply x by 3. Call the result y.
In exact arithmetic we know (1/3)*3 is exactly 1. But the x value you defined in step 1 is not one third. It is slightly smaller than one third because you rounded off one third to fit it into x. If you've written one more decimal place in step 1 you'd have an x that's closer to one third than the x you actually used in step 2. Therefore y will not be 1. The value stored in y will be slightly smaller than 1.
Just as x in the example above is not exactly one third, 0.01 is not exactly one one-hundredth and 0.001 is not exactly one one-thousandth. We can use Symbolic Math Toolbox to convert them to numbers of the form N*2^e for integers N and e. The denominators are not exactly 100 or 1000 times the numerators respectively.
hundredth = sym(0.01, 'f')
thousandth = sym(0.001, 'f')
John D'Errico on 23 Sep 2022
Edited: John D'Errico on 23 Sep 2022
I'll say the same thing, but differently.
As @Steven Lord points out, you cannot represent the fraction 1/3 exactly as a decimal. And while it seems like you could represent 0.01 exacly as a decimal, you have a problem. That is because computers generally do not use decimals internally. They use an IEEE binary form. Yes, they interface with you as if the numbers were in decimal. But are they that way internally? NO.
So if we try to represent the fraction 1/100 = 0.01, in binary, the result is an infinitely repeating BINARY number. It might look something like this:
Here I've used the ones to represent negative powers of 2. Personally, I call it a bicimal expansion.But those ones and zeros repeat infinitely.
And that means just because you write 0.01 in MATLAB, you don't get that number EXACTLY. In fact, you will get this:
That is the closest number (as stored in BINARY) that MATLAB could find to approximate 0.01. It is within one bit in the least significant bit. But it is not truly exact. And that is because it cannot be exactly 0.01.
NEVER compare a floating point number to another floating point number. Well, at least unless you know enough about floating point numbers and how they are stored to know when you can do that with any degree of safety. And even then you probably should use a tolerance to compare floating point numbers for equality.