Why is MATLAB messing up this very simple calculation.

103 Ansichten (letzte 30 Tage)
Garrett Thomas
Garrett Thomas am 9 Okt. 2018
Bearbeitet: Viet Ha Tran am 14 Aug. 2020
I was trying to tutor MATLAB to one of the underclassman I tutor. I came across an error that I initially could not fix. I eventually found the error but it isn't my error. MATLAB calculated the wrong number! -2.9982*5=-14.991 not -2.9982*5=-14.991000000000001. I can avoid using this calculation in the code but I just want to know what is causing this silly error so I can avoid it again.
  3 Kommentare
Stephen23
Stephen23 am 13 Aug. 2020
Bearbeitet: Stephen23 am 13 Aug. 2020
@Viet Ha Tran: MATLAB does the calculation following the IEEE 754 standard. You can compare this against other tools that also follow IEEE 754 and get the same answer.
Windows Calculator uses an abritrary-precision arithmetic library (see https://en.wikipedia.org/wiki/Windows_Calculator), I could not find any relevant documentation online in the short time I spent searching. Possibly it uses some decimal number format, or just a really high precision binary format for storing those values.
Windows Office Excel certainly stores numbers in memory as double (i.e. binary floating point) but as far as I am aware does not document how they use these in calculations. Excel has an option to change the calculation precision based on the display format (search for "Precision as displayed"), truncates digits beyond 15 significiant figures to 0, and its development team is known to have written their own C compiler, all of which indicate that they do some of their own magic and probably also use some arbitrary precision arithmetic library.
Summary: Windows applications do not openly document how they work. MATLAB follows an international standard for binary floating point numbers.
Viet Ha Tran
Viet Ha Tran am 14 Aug. 2020
Bearbeitet: Viet Ha Tran am 14 Aug. 2020
Thank you for your quick and clear answer. I have that problem when running my script which will decide what to do depending on the comparision above. My idea now is to set, say, 10e-12 difference as zero. I see some good discussions on google search, will figure it out. Thanks again.

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Stephen23
Stephen23 am 9 Okt. 2018
Bearbeitet: Stephen23 am 10 Okt. 2018
"MATLAB calculated the wrong number!"
Nope, MATLAB calculated the right number.
The reason is simply that the value -2.9982 cannot be represented exactly using binary floating point numbers, so any calculation involving that number will inevitably accumulate some floating point error.
In exactly the same way that you cannot write 1/3 exactly using a finite decimal fraction, it is impossible to store -2.9982 exactly using a finite binary floating point number. So although you might think that you have -2.9982, in fact the real values stored in computer memory is slightly different from this. And so when you perform some calculation on it, the calculation collects this floating point error, so that the final total is not going to be exactly equal to -14.991 (unless your calculation involves only powers of two).
What you see printed in the command window is the closest representation to 5 or 16 significant digits, depending on your current format setting. To see the "real" value download James Tursa's FEX submission:
Use James Tursa's num2strexact and you will see that that number does not really have the exact value -2.9982. All you are looking at is a representation of those floating point numbers displayed in the command window, to the precision defined by your format setting. Just because you see -2.9982 displayed in the command window tells you nothing about the real floating point number's value.
Note that you can change how the value is displayed by changing the format.
You need to learn about the limits of floating point numbers. Start by reading these:
This is worth reading as well:
  5 Kommentare
Garrett Thomas
Garrett Thomas am 10 Okt. 2018
Learn something new every day
Walter Roberson
Walter Roberson am 10 Okt. 2018
IEEE 754 also defines a decimal floating point format, but the only systems I have heard of that implement it in hardware are some IBM Z9 systems.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Micha E
Micha E am 4 Apr. 2019
I have some problems with "wrong" calculations in Matlab too. I like to use some calculations to create idices, pretty simple and I always get positive integer by calculating it with hand.
example in Matlab:
>> 203/200*1000
ans =
1.0150e+03
by using it as index brings an error
>> 203/200*1000-203*1000/200
ans =
-1.1369e-13
shows why.
h=(1:1:1000)';
for i=1:1000
h(i)=h(i)/200*200-h(i)*200/200;
end
The code shows were I have problems: i=7,14,28,29....
Is it a problem of my PC or Matlab ?... very strange. An answer would be great!
Thanks, Michael
  1 Kommentar
John D'Errico
John D'Errico am 4 Apr. 2019
Bearbeitet: John D'Errico am 4 Apr. 2019
Please don't answer a question with another question. Worse, had you bothered to read the answers to the question you attached this too, you would learn something about floating point numbers.
What is 203/200? Is it an integer? Is it exactly representable as a floating point number, using a binary storage form? (Hint: no. Read the answer.) While you might think that 203/200 is 1.015, that is not what was computed.
sprintf('%0.55f',203/200)
ans =
'1.0149999999999999023003738329862244427204132080078125000'
The number 1.015 cannot be stored exactly as a number using binary. READ THE ABOVE ANSWER. So, instead, the intermediate result is created as the mess above, an approximation to 1.015, but not in fact 1.015. In binary form, we would see the expansion of 1.015 as the infinite binary number
1.0000001111010111000010100011110101110000101000111101...
This is a repeating, non-terminating binary number, with a repeating part that appears to be: "11110101110000101000".
Then when you multiply it by 1000, is there any reason to expect the result to be an exact integer? Again, no, because MATLAB could not represent the previous computation exactly. Some information was lost in the intermediate computation. And information, once lost, is not easily recovered, often not at all.
sprintf('%0.55f',203/200*1000)
ans =
'1014.9999999999998863131622783839702606201171875000000000000'
If it is not an integer, then it is not a valid index.
Why is there a difference when you do the operation in a different order? Thus, what is this intermediate result?
203*1000
Is that an integer? Yes. Is it less than 2^53? Yes. Is it evenly divisible by 200, still as an integer? Again, clearly yes. So MATLAB has no problem with the computation 203*1000/200. The result in that order will in fact be a positive integer, and thus potentially a valid index.
Remember that intermediate results are computed. The order in which you perform a computation DOES matter. Computer programming is NOT mathematics, only an approximation thereof. While it is often a good approximation, it is only an APPROXIMATION. And you need to understand when it is only approximate, because for SOME computations you are able to work with integers without approximation. All of this means that while you assume the commutative law should apply on computations like this, it need not in fact apply exactly.
So read the answer you apparently ignored. And when you have a question, don't hijack another question with a non-answer. Post a question.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Matrix Indexing finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by