Bug in matlab R2012b version

4 ビュー (過去 30 日間)
scarzo
scarzo 2014 年 7 月 22 日
コメント済み: Sean de Wolski 2014 年 7 月 25 日
Hello,
I use the MATLAB R2012b version and when I try this:
0.5:0.1:0.8 the answer is:
ans =
Columns 1 through 3
5.000000000000000e-01 6.000000000000000e-01 7.000000000000001e-01
Column 4
8.000000000000000e-01
Why the third term is not strictly equal to 0.7? Furthermore when I try 0.5:0.1:0.9 the bug disappears!
Do you have an answer? Note: (as a reminder go to "HOME", "Preferences" and select "long e")
Thanks in advance

採用された回答

David Young
David Young 2014 年 7 月 23 日
Not really an answer, but a suggestion in the light of the observations made in the question and in other answers.
In general, I think it makes sense to use the colon operator only for integer cases. That is, it's good for iteration counting ( for i = 1:10 ) and array indexing ( x(3:17) ) but it's not so suitable for getting a linear space when there are non-integers involved.
In such cases, you get more control and predictability using linspace. The downside is that you have to compute the number of elements in the sequence yourself, but this is really an advantage because you choose what is going on. So instead of
0.5 : 0.1 : 0.8
you'd use
linspace( 0.5, 0.8, round((0.8 - 0.5)/0.1) + 1 )
In general, the increment will not be exactly divisible into the space between the end points. The big advantage of using linspace is that it makes you think through exactly what you want to do about this: adjust the end points, or adjust the increment.
Of course, there will be exceptions to this "colon for integers only, otherwise linspace" rule, but I think it's a good starting position.
[Incidentally, I have a guess about what is going on with the colon operator. Rounding errors mean that in a sequence like 0.5:0.1:0.8 you can't predict whether the result will include 0.8 at the end or not, because 0.5 + 3*0.1 might evaluate to just less than 0.8. I suspect the colon operator tries to make this predictable by tweaking the increment a little bit. Which might be fine if it was documented.]
  5 件のコメント
Daniel Shub
Daniel Shub 2014 年 7 月 24 日
@Sean I have already raised it as a documentation bug, but thanks. I am a little worried that the colon function has, or will, change.
Sean de Wolski
Sean de Wolski 2014 年 7 月 25 日
Here you go Daniel. Thanks for bring it up.

サインインしてコメントする。

その他の回答 (8 件)

James Tursa
James Tursa 2014 年 7 月 22 日
編集済み: James Tursa 2014 年 7 月 23 日
Others have already adequately answered your question. But to help you gain a better understanding of this I will point you to an FEX submission, NUM2STREXACT, which prints the exact floating point binary to decimal conversion for any number. Bottom line is that the majority of numbers you are working with cannot be represented exactly in IEEE double (as others have already written). To see what the exact decimal conversions are for your examples:
>> x = num2strexact(0.5:0.1:0.8)
x =
'0.5' [1x55 char] [1x55 char] [1x54 char]
>> x{1}
ans =
0.5
>> x{2}
ans =
0.59999999999999997779553950749686919152736663818359375
>> x{3}
ans =
0.70000000000000006661338147750939242541790008544921875
>> x{4}
ans =
0.8000000000000000444089209850062616169452667236328125
And here is your second example:
>> x = num2strexact(0.5:0.1:0.9)
x =
'0.5' [1x55 char] [1x54 char] [1x54 char] [1x55 char]
>> x{1}
ans =
0.5
>> x{2}
ans =
0.59999999999999997779553950749686919152736663818359375
>> x{3}
ans =
0.6999999999999999555910790149937383830547332763671875
>> x{4}
ans =
0.8000000000000000444089209850062616169452667236328125
>> x{5}
ans =
0.90000000000000002220446049250313080847263336181640625
Note that the underlying algorithm used by the COLON operator does not guarantee that individual element results will necessarily match up even when the starting element and the delta are the same (this is due to methods used for minimizing accumulated errors, see the COLON doc for more details)
You can find NUM2STREXACT here:
EDIT
For completeness I will add these results as well:
>> x = num2strexact([0.5 0.5+0.1 0.5+2*0.1 0.5+3*0.1 0.5+4*0.1])
x =
'0.5' [1x55 char] [1x54 char] [1x54 char] [1x55 char]
>> x{2}
ans =
0.59999999999999997779553950749686919152736663818359375
>> x{3}
ans =
0.6999999999999999555910790149937383830547332763671875
>> x{4}
ans =
0.8000000000000000444089209850062616169452667236328125
>> x{5}
ans =
0.90000000000000002220446049250313080847263336181640625
>> x = num2strexact(linspace(0.5,0.8,4))
x =
'0.5' [1x55 char] [1x55 char] [1x54 char]
>> x{2}
ans =
0.59999999999999997779553950749686919152736663818359375
>> x{3}
ans =
0.70000000000000006661338147750939242541790008544921875
>> x{4}
ans =
0.8000000000000000444089209850062616169452667236328125
>> x = num2strexact(linspace(0.5,0.9,5))
x =
'0.5' [1x55 char] [1x54 char] [1x54 char] [1x55 char]
>> x{2}
ans =
0.59999999999999997779553950749686919152736663818359375
>> x{3}
ans =
0.6999999999999999555910790149937383830547332763671875
>> x{4}
ans =
0.8000000000000000444089209850062616169452667236328125
>> x{5}
ans =
0.90000000000000002220446049250313080847263336181640625
>> num2strexact(0.7)
ans =
0.6999999999999999555910790149937383830547332763671875
  5 件のコメント
Image Analyst
Image Analyst 2014 年 7 月 25 日
James Tursa
James Tursa 2014 年 7 月 25 日
Thanks. I knew I read this somewhere but just couldn't find it.

サインインしてコメントする。


the cyclist
the cyclist 2014 年 7 月 22 日
It's not a bug. It's a reality of floating point arithmetic. See this page as one possible starting point to increase your understanding.

Roger Stafford
Roger Stafford 2014 年 7 月 22 日
編集済み: Roger Stafford 2014 年 7 月 22 日
The reality, Scarzo, is that because matlab's 'double' uses a binary number representation, it can never represent any of the fractions 0.6, 0.7, 0.8, or 0.9 exactly, though it can achieve 0.5 precisely. It is analogous to trying to represent 1/3 exactly as a decimal fraction, which is impossible.
However, it is also true that with most formats the displays of stored 'double' numbers are also not exact. The net result is that some numbers may appear to be represented exactly when in fact they aren't, such as is the case with 6.000000000000000e-01 or 8.000000000000000e-01 in your example. If you were to make a careful study of the corresponding numbers actually in the computer, they are not, and cannot be, exactly 6/10 and 8/10, even though the display indicates that they are. Even when the computer claims that the logical proposition A(3)==.7 is true, it is really only saying that both slightly erroneous representations of 0.7 are the same.
In all such cases, however, the difference between the exact fraction and the machine value differ by an error which is something like half the value of the least binary bit or less. Since in 'double' there are 53 significand bits, this is a very small amount relative to the size of the number. It is the best the machine can do. In all fairness, this cannot be considered as a "bug", any more than a decimal calculator can be considered as having a bug when it gives 0.3333333333 as the answer to 1 divided by 3. It's the best it can do.
  5 件のコメント
Daniel Shub
Daniel Shub 2014 年 7 月 24 日
@David I have put in a service request to get access to the technical solution. Will see what happens.
Image Analyst
Image Analyst 2014 年 7 月 25 日

サインインしてコメントする。


Mischa Kim
Mischa Kim 2014 年 7 月 22 日
編集済み: Mischa Kim 2014 年 7 月 22 日
Scarzo, that's not a bug. Check out this answer for reference.

Wayne King
Wayne King 2014 年 7 月 22 日
In R2012b with win7 and a 64-bit machine I get the following:
A = 0.5:0.1:.8;
abs(A(3)-0.7)
ans =
1.1102e-16
eps(.7)
ans =
1.1102e-16
Note that:
abs(A(3)-0.7)
is equal to
eps(0.7) %see the help for eps()
So you do obtain the closest floating point number of 0.7 as the 3rd element as expected.

scarzo
scarzo 2014 年 7 月 22 日
Thanks for your answers but why the delta disappears in the third term when I try 0.5:0.1:0.9 ?
  2 件のコメント
Image Analyst
Image Analyst 2014 年 7 月 22 日
For clarity, here is your code:
clc;
A = 0.5:0.1:.8
abs(A(3)-0.7)
A = 0.5:0.1:.9
abs(A(3)-0.7)
and here is the results:
A =
0.5000 0.6000 0.7000 0.8000
ans =
1.1102e-16
A =
0.5000 0.6000 0.7000 0.8000 0.9000
ans =
0
scarzo
scarzo 2014 年 7 月 22 日
編集済み: scarzo 2014 年 7 月 22 日
Exactly! Does it make any sense?

サインインしてコメントする。


scarzo
scarzo 2014 年 7 月 23 日
編集済み: scarzo 2014 年 7 月 23 日
My explanation was unclear thank you David for clarifying my problem. Thanks to all of you for your answers but as David said I think that anyone has offered a right explanation.

Daniel Shub
Daniel Shub 2014 年 7 月 24 日
The colon operator in MATLAB with non-integers is a tricky beast. Not only do you need to worry about round off errors associated with working with floating point numbers, but you need to think about how those errors accumulate. Since the COLON function is closed source, you cannot see how it solves this problem. The MathWorks used to have a nice technical solution, now only available on the way back machine, on the issue and made MATLAB code available. The documentation on COLON changed between r2013a and r2013b, so the source code may no longer be an accurate representation of the COLON function anymore.

カテゴリ

Help Center および File ExchangeLogical についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by