Failure in a simple division
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
이전 댓글 표시
1 개 추천
Hi everybody, I found a litle bug in a code of mine related to a failure in a simple division: >> 473/10 ans = 47.299999999999997 >> why does this happen? Have I done something to wrong in preferences or setting option? How to fix it? Help me please
채택된 답변
Star Strider
2015년 11월 12일
2 개 추천
Not a bug at all. It’s ‘floating point approximation error’. Representing decimal numbers — including integers — in binary is somewhat analogous to representing the fraction 1/3 in decimal: 0.3333.... No matter how long the sequence, it will never equal 1/3.
댓글 수: 11
James Tursa
2015년 11월 12일
Why the "including integers" side comment?
John D'Errico
2015년 11월 12일
Integers are always exactly representable as a double, UNLESS they exceed 2^53-1 in magnitude. But the problem with large integers is due to a slightly different reason than Star suggests.
James Tursa
2015년 11월 12일
Exactly, hence my comment.
Star Strider
2015년 11월 12일
My intent is to say that even if the expected result is an integer, operations on them can produce the approximation error. Should have been clearer.
Gino Massafra
2015년 11월 13일
Sorry, my porpose was to know if and how can I fix this. Can this be fixed? Or should I always set conditions like: if(abs(x-y)<eps)... instead of if(x==y)..... ???
"how can I fix this" does not make sense, because nothing is actually broken: this is simply how floating point values are.
It is your job as the script writer or programmer to take these floating point errors into account. As you suggest using tolerances is a common and effective way of achieving this (search this forum for examples).
I agree with Stephen. Nothing is broken.
I would set conditions, as you illustrated. Several functions in the most recent releases, such as uniquetol and ismembertol allow tolerances as arguments.
Tolerances are necessary as you have discovered, because even using the round function to round it to one digit to the right of the decimal will not result in 47.3, nor will this roundn anonymous function that emulates it:
roundn = @(x,n) 10^-n .* round(x * 10^n);
a = 473/10
b = roundn(a,1) % Use Anonymous Function
c = round(a,1) % R2015b Implementation
a =
47.299999999999997
b =
47.300000000000004
c =
47.299999999999997
Only one computer I am aware of — the IBM 1620 — used decimal arithmetic, using lookup tables to do its calculations. It might have been able to do this calculation exactly. (It was necessary to load the tables and the machine code that loaded them as the first five cards of your PDQ FORTRAN program deck. An IBM engineer I talked with later told me that they called it the ‘CADET’ computer: ‘Can’t Add, Doesn’t Even Try’!)
Joseph
2020년 1월 6일
I ran into the same issue and this answer seems to me to be incomplete.
Consider the following case: test=str2double(MATLABver.Version);
test is now a double precision number equalling 9.7.
The code (test==9.7) results in a logical 1
If we then perform the following operation:
>> test=(test*10)/10
test =
9.699999999999999
The code (test==9.7) still results in a logical 1
So yes there appears to be 'floating point approximation error' but something has changed in how Matlab is presenting the numbers, so at the least there is a failure of reversability. Furthermore, it appears to be taking this error into account during the comparison. So why did the poster run into a problem originally? Is there some case where Matlab should also have taken it into account and did not?
Star Strider
2020년 1월 6일
@Joseph — The original post is more than four years old, during which there have been eight MATLAB versions released (assuming the poster was using R2015b, more otherwise), each with significant improvements.
I have no desire at all to download and install R2015b to test it against R2019b with this problem. If you do, post the results back here.
"I ran into the same issue and this answer seems to me to be incomplete."
Nope, the answer is still quite correct. All of your values happen to resolve to exactly the same floating point number (and there is nothing unusual about that, it certainly can happen, although should definitely not be relied upon):
>> test = str2double('9.7');
>> num2strexact(test)
ans =
9.699999999999999289457264239899814128875732421875
>> test = (test*10)/10;
>> num2strexact(test)
ans =
9.699999999999999289457264239899814128875732421875
>> num2strexact(9.7)
ans =
9.699999999999999289457264239899814128875732421875
"something has changed in how Matlab is presenting the numbers"
I very much doubt that. Do you have any supporting examples?
"...so at the least there is a failure of reversability"
As operations on floating point numbers are neither commutative nor associative, I don't see how you can describe their documented behavior as a "failure".
"So why did the poster run into a problem originally?"
What problem? The original question just showed a double floating point value displayed correctly according to MATLAB's format documentation:
>> 473/10
ans =
47.299999999999997
>> num2strexact(473/10)
ans =
4.72999999999999971578290569595992565155029296875e1
I just tried it on three MATLAB versions and it looks exactly the same on each of them. Not only that, but the original question did not mention any logical equivalency operation, so it is not clear what you think their "problem" was, or how it relates to your comment and examples.
"Is there some case where Matlab should also have taken it into account and did not?"
I very much doubt that. Do you have any supporting examples?
So far everything in your comment and in the original question are explained perfectly by the well-documented behavior of binary floating point numbers. Nothing seems to have changed.
Star Strider
2020년 1월 6일
@Stephen — Thank you!
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
