Simple question: How to setup Matlab to calculate more precisely?

2 vues (au cours des 30 derniers jours)
Manuela Gräfe
Manuela Gräfe le 31 Mai 2017
Commenté : Walter Roberson le 1 Juin 2017
Hello,
please check the following example:
A=400;
B=220;
C=1.5;
D=(B/A)*C;
E=(B*C)/A;
F=D-E %%%%=1.110223024625157e-16
In my opinion F must be zero?
Has anyone an explanation for this?
Thanks

Réponses (2)

Walter Roberson
Walter Roberson le 31 Mai 2017
If you have the symbolic toolbox:
A = sym(400);
B = sym(220);
C = sym(1.5);
D = (B/A)*C;
E = (B*C)/A;
F = D-E
However, if you use this, you need to be aware of how sym converts floating point numbers. Read about the conversion flags at https://www.mathworks.com/help/symbolic/sym.html#input_argument_d0e141952 and read the examples at https://www.mathworks.com/help/symbolic/sym.html#bu1rs8g-1
And remember that the problem occurs in any finite number base. For example in 3 digit decimal,
v = 1/3
1 * v -> 0.333
2 * v -> 0.666
3 * v -> 0.999
1 - 3 * v -> 0.001
Calculations in any finite representation are not the same as algebraic calculations on rationals: order matters.

David Goodmanson
David Goodmanson le 31 Mai 2017
Modifié(e) : David Goodmanson le 1 Juin 2017
Hi Manuela, you have just discovered one of the features of floating point arithmetic. Matlab uses 64 memory bits for a floating point number, which corresponds to about 15 decimal digits worth of precision. When you multiply and divide quantities in different orders, there can be variations in what happens to the last bit. So you can get perfectly normal disagreement, on the order of 1e-16, in the answers.
With the symbolic toolbox it is possible to obtain precision to many, many more digits but that is much slower and mostly not necessary, once you know what floating point numbers are up to.
Matlab can represent integers exactly in the range of approximately +-9e15
  3 commentaires
David Goodmanson
David Goodmanson le 31 Mai 2017
Modifié(e) : David Goodmanson le 31 Mai 2017
the most common situation is when you calculate two numbers x and y that some of the time 'should' be equal, and want to do the following:
if x==y
(do something)
else
(do something else)
end
If x and y differ by 1e-16 or some such, then the first part of the if statement mysteriously never happens. You can guard against that in various ways. If you know that x and y are supposed to come out as integers you can use x = round(x) etc. first. The most common approach is to replace the first line with
if abs(x-y) < 1e-10
or whatever tolerance you think is appropriate.
Other situations are not a problem. For example
for j = 1:1000
for k = 1:1000
if j==k
(do something)
end
end
end
This always works since you are creating integers and comparing them.
Walter Roberson
Walter Roberson le 1 Juin 2017
I like to point out that if you calculate the same expression in two different ways, then the result might be different. Even ((A+B)+C) compared to (A+(B+C)) can give you different results.
Therefore the only time it is safe to compare floating point numbers for equality is if they are extracted from the same source. For example it is safe to test
A == min(A)
because the min(A) will be a bitwise-identical copy of some element of A

Connectez-vous pour commenter.

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by