MATLAB: Isn’t MATLAB counting this as equal to 1

floating pointif statementMATLAB

I've been writing a code, a small part of which checks whether some of the inputs sum to 1 (as they're all proportions of a whole). If they do, the code continues. If not, the code stops and throws up an error message.
a = 0.4;
b = 0.3;
c = 0.2;
d = 0.1;
total = [a,b,c,d];
if sum(total) ~= 1
warning('Sum of a,b,c,d must be 1.')
return
end
The example I've given here DOES NOT WORK, even though a+b+c+d = 1. It throws up the error message and stops the script.
To be clear, this works fine for a,b,c and d = 0.25. It works for a = 0.5, b = 0.4, c and d = 0.05. It doesn't work for the example I've given, and it doesn't work for a,b,c = 0.3, d = 0.1. I haven't checked other combinations exhaustively.
Any help would be greatly appreciated, thanks.

Best Answer

None of 0.4, 0.3, 0.2, or 0.1 can be exactly represented in IEEE double precision. See the "One-tenth" and "Hexadecimal format" sections of this post on Cleve Moler's blog for a bit more of an explanation. So those are not exactly equal to four-tenths, three-tenths, two-tenths, or one-tenth. This is not a MATLAB problem (other languages will behave the exact same way if they use double precision), this is a "double precision numbers aren't infinitely precise" situation.
To give a similar scenario that doesn't involve computers, take out a piece of paper and a pen or pencil (or anything you can use to write and something to write on.) Divide 1 by 3 to as many decimal places as you want and can write down. You're not allowed to just say that it's 0.3 repeating, you have to write out all the decimal places you want to use in the next step.
Now multiply the answer you computed in the first step by 3. Symbolically, (one third) * 3 is exactly 1. Practically, (the approximation you computed to one third) * 3 is not exactly 1.
The original code posted by madhan ravi has a mistake in it. [I saw it was edited, but I'm not sure if it was edited to correct the mistake.] Instead of this line:
if (sum(total) == 1) < 1e-4
you need to use:
if abs(sum(total) - 1) < 1e-4
This second line computes the distance between the sum of your vector and 1 (calling abs means we don't care which one is larger, we're just getting the absolute distance) and checks if that distance is "close enough" (which in this code is defined as a distance smaller than 1e-4.) If it is "close enough" the if statement's body will execute.
Added: You may wonder why it worked with 0.25, why sum([0.25 0.25 0.25 0.25]) was exactly 1. Unlike 0.4, 0.3, 0.2, and 0.1 the number 0.25 can be exactly represented in IEEE double precision. Using the fraction/mantissa and exponent notation from the "Single and Double Precision" section in Cleve's blog post, f is 0 and e is -2.