Wrong sum 50 + 0.01

3 views (last 30 days)
Alberto Cavarzeran
Alberto Cavarzeran on 28 Oct 2022
Commented: Walter Roberson on 28 Oct 2022
Hi, while working on Matlab from an Excell worksheet I get this problem when adding 0.01 to 50 or to another integer between 10 and 100 (for number bigger than 100 the error does not appear in the format lon representation of the number).
Here an example of this problem:
And this is what happen for other integers:
On the other hand the value stored in the workspace is correct:
I'm using the last version of the software r2022a and this problem appears also on other pc, but it works properly when I open matlab directly and not through an Excell worksheet.
How can I fix it?

Accepted Answer

Davide Masiello
Davide Masiello on 28 Oct 2022
Edited: Davide Masiello on 28 Oct 2022
I don't think this is an issue at all, but it rather has to do with the max accuracy MatLab uses to store numbers.
Such accuracy is
format long
eps
ans =
2.220446049250313e-16
where, eps is the distance between a number and the next larger number.
In other words matlab does not distinguish between
50+0.01
ans =
50.009999999999998
and
50+0.01+eps/2
ans =
50.009999999999998
Or in other words still, the sum is indeed 50.01, but if you ask to look at more than 15 decimal digits, then Matlab can't help but introduce an uncertainty.
  3 Comments
John D'Errico
John D'Errico on 28 Oct 2022
Edited: John D'Errico on 28 Oct 2022
Good comment by @Rik, in that the answer is not the max acccuracy, but instead a finite representartion of numbers in a binary form. And this goes to the IEEE standard, not really even to MATLAB.
Doubles are stored as 52 binary bits for the mantissa. The limit of 52 is what @Davide Masiello has pointed out, but really, it is the fact that binary is used here, in a floating point storage scheme. ANY finite number of bits would be too few to exactly represent most fractions.
So, as pointed out, fractions like 1/3 will NEVER be exactly representable in a finite number of "digits" in a floating point form (unless you use Ternary, or some variation of it, like base 6 or base 12.) The same thing applies to binary storage forms. In binary forms, ONLY fractions that are integral multiples of a negative power of 2 can be represented
And yes, this is surely counter-intuituve to many, that numbers like 0.1 = 1/10 or 0.2 = 1/5 are NOT exactly representable in binary, yet 0.5=1/2 IS representable exactly in binary.
For example, I like to use the name bicimal to indicate the string of binary bits that would represent a number, like this:
1/5 = 0.0011001100110011001100110011001100110011001100110011010... "b"
So 1/5, in terms of negative powers of 2, would be represented as the infinitely repeating string of bits, where we see the pattern '0011' repeat forever. If you prefer...
1/5 = (2^-3 + 2^-4 + 2^-7 + 2^-8) + (2^-11 + 2^-12 + 2^-15 + 2^-16) + ....
I've grouped the repeating form there in the sum using parens. For example,
format long g
(2^-3 + 2^-4 + 2^-7 + 2^-8)
ans =
0.19921875
(2^-3 + 2^-4 + 2^-7 + 2^-8) + (2^-11 + 2^-12 + 2^-15 + 2^-16)
ans =
0.199996948242188
(2^-3 + 2^-4 + 2^-7 + 2^-8) + (2^-11 + 2^-12 + 2^-15 + 2^-16) + (2^-19 + 2^-20 + 2^-23 + 2^-24)
ans =
0.199999988079071
(2^-3 + 2^-4 + 2^-7 + 2^-8) + (2^-11 + 2^-12 + 2^-15 + 2^-16) + (2^-19 + 2^-20 + 2^-23 + 2^-24) + (2^-27 + 2^-28 + 2^-31 + 2^-32)
ans =
0.199999999953434
As you should see, we can come arbitrarily close to 1/5 in that approximation, but a double will never store that number as accurately as you may wish. In turn, that means you CANNOT store the fraction 1/5 (or 1/10 for that matter) exactly as a double. Yet at the same time we would write 1/2 as
1/2 = 0.100000000000000000000000000000000000000000000000000000... "b"
Similarly, 1/10 has the same repeating infinitely pattern as does 1/5 with '0011', but we just pre-pend an extra zero at the beginning.
1/10 = 0.00011001100110011001100110011001100110011001100110011010... "b"
Anyway, the problem is not the fact of the maximum accuracy used, since ANY floating point form will fail to represent some simple fractions exactly, but of the fact that a floating point form is used at all. But if you want to see truly fast computations done, then floating point arithmetic is an absolute necessity. And I seriously doubt that anyone would want to have MATLAB do all of its computations in a symbolic form, with literally infinitely many digits stored for every number. Every computation would then be blazingly slow.
Intead, people learn to understand the limits of a floating point form as they grow their computational skills. They learn to use tolerances, to never trust the least significant bits of any number, at least until they fully, completely understand avery aspect of the issues that will arise. And even then, it helps to be careful.
Walter Roberson
Walter Roberson on 28 Oct 2022
Further: the problem is not base 2. If you pick any finite integer numeric base, B (for example, base 60 or base 7592) then 1/C is an infinitely repeating number in base B if there is any factor of C that does not divide into B. Base 60 for example can exactly represent 1/2, 1/3, 1/4, 1/5, 1/6, 1/8, 1/9, 1/10, 1/12, 1/15, 1/16, 1/18, 1/20, 1/24, 1/25, 1/27, 1/30...and others... but not 1/7 1/11 1/13 1/14 1/17 1/19 1/21 1/22 1/23 1/29...
That is, it is a fundamental limitation of finite representation positional in mathematics.

Sign in to comment.

More Answers (0)

Categories

Find more on Get Started with MATLAB in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!