.NET에서 이중 곱셈이 끊어 집니까?
이 질문에 이미 답변이 있습니다.
- 부동 소수점 수학이 깨졌습니까? 31 답변
C #에서 다음 식을 실행하면 :
double i = 10*0.69;
i
입니다 : 6.8999999999999995
. 왜?
1/3과 같은 숫자는 무한 반복 소수점 자리가 있기 때문에 이진수로 표현하기 어려울 수 있지만 0.69의 경우는 아닙니다. 그리고 0.69는 쉽게 이진수로 표현할 수 있습니다. 하나는 69를 나타내는 이진수이고 다른 하나는 소수점 위치를 나타냅니다.
이 문제를 어떻게 해결합니까? decimal
유형을 사용 하시겠습니까?
부동 소수점 산술과 데이터 저장 방법을 잘못 이해했기 때문입니다.
실제로이 특정 경우에 실행 시간에 코드가 실제로 산술을 수행하지 않습니다. 컴파일러 가이를 수행 한 다음 생성 된 실행 파일에 상수를 저장합니다. 그러나 6.9의 정확한 값을 저장할 수는 없습니다. 그 값은 부동 소수점 형식으로 정확하게 표현 될 수 없기 때문입니다. 마치 1/3이 유한 십진 표현으로 정확하게 저장 될 수없는 것처럼 요.
왜 프레임 워크가이 문제를 해결하지 않고이 문제를 내게 숨기고 올바른 답을 제공하지 않습니다. 0.69 !!!
딜버트 매니저처럼 행동하지 말고 컴퓨터는 멋지고 멋지지만 한계가 있음을 받아들이십시오. 당신의 특정한 경우에, 당신이 특별히하지 말라고 말했기 때문에 문제를 "숨기기"만하는 것이 아닙니다. 언어 (컴퓨터)는 사용자가 선택하지 않은 형식에 대한 대안을 제공합니다. 당신은 double을 선택했는데, 이것은 십진수보다 특정한 장점과 특정한 단점이 있습니다. 이제 답을 알면 단점이 마술처럼 사라지지 않는다는 사실에 화가납니다.
프로그래머는 관리자에게 이러한 단점을 숨길 책임이 있으며이를 수행하는 방법에는 여러 가지가 있습니다. 그러나 C #의 제작자는 부동 소수점이 올바르게 작동하도록 할 책임이 있으며 올바른 부동 소수점으로 인해 때때로 잘못된 수학이 발생합니다.
무한한 비트가 없기 때문에 다른 모든 숫자 저장 방법도 마찬가지입니다. 프로그래머로서 우리의 임무는 제한된 자원으로 멋진 일이 일어나도록하는 것입니다. 90 %의 길을 안내해 주며 횃불을 집으로 가져 가세요.
그리고 0.69는 쉽게 이진수로 표현할 수 있습니다. 하나는 69를 나타내는 이진수이고 다른 하나는 소수점 위치를 나타냅니다 .
저는 이것이 일반적인 실수라고 생각합니다. 부동 소수점 숫자가 10 진수 인 것처럼 생각하고 있습니다 (즉, 십진수-따라서 강조합니다).
그래서-당신은이 두 배에 두 개의 정수 부분이 있다고 생각하고 있습니다 : 69 와 100 으로 나누면 움직일 소수점 자리를 얻습니다. 이것은 또한
69 x 10의 -2 제곱 으로 표현 될 수 있습니다 .
그러나 수레는 '점의 위치'를 base-2 로 저장합니다 .
float는 실제로 다음과 같이 저장됩니다.
68999999999999995 x 2의 큰 음수의 거듭 제곱
일단 익숙해지면 문제가되지는 않습니다. 대부분의 사람들은 1/3이 소수 또는 백분율로 정확하게 표현 될 수 없다는 것을 알고 예상합니다. 단지 2 진법으로 표현할 수없는 분수가 다르다는 것입니다.
하지만 왜 프레임 워크가이 문제를 해결하지 않고이 문제를 내게 숨기고 올바른 답을 제공하지 않습니다. 0.69 !!!
이진 부동 소수점 을 사용하도록 지시 했고 해결책은 10 진수 부동 소수점 을 사용하는 것이므로 프레임 워크가 지정한 유형을 무시하고 대신 10 진수 를 사용해야한다고 제안하고 있습니다 . 하드웨어.
보다 효율적인 솔루션은 표현의 전체 값을 출력하지 않고 출력에 필요한 정확도를 명시 적으로 지정하는 것입니다. 출력을 소수점 이하 두 자리로 포맷하면 예상 한 결과를 볼 수 있습니다. 그러나 이것이 금융 응용 프로그램 십진수 라면 정확히 사용해야 할 것입니다-Superman III (및 Office Space)는 당신을 보지 못했습니다.)
그것은 모두 무한 범위의 유한 근사이며, 단지 십진수 와 이중 은 다른 근사 세트를 사용 한다는 점에 유의하십시오 . 소수 의 장점은 계산을 직접 수행 할 때와 동일한 근사치를 생성한다는 것입니다. 예를 들어 1/3을 계산하면 결국 '충분히 좋다'면 3의 쓰기를 중단하게됩니다.
같은 이유로 십진법에서 1/3이 0.3333333333333333333333333333333333333333333으로 나오고 무한히 긴 정확한 분수가 아닙니다.
이 문제를 해결하려면 (예 : 화면에 표시) 다음을 시도하십시오.
double i = (double) Decimal.Multiply(10, (Decimal) 0.69);
모든 사람이 첫 번째 질문에 답한 것 같지만 두 번째 부분은 무시했습니다.
참조 URL : https://stackoverflow.com/questions/1420752/is-double-multiplication-broken-in-net
'programing' 카테고리의 다른 글
Spark : Spark Shell에서 Spark 파일을 실행하는 방법 (0) | 2021.01.16 |
---|---|
인수 밑줄이있는 디 바운스 함수 (0) | 2021.01.16 |
Python의 항목 빈도 수 (0) | 2021.01.16 |
JQuery를 사용하여 CKEditor의 콘텐츠를 어떻게 얻을 수 있습니까? (0) | 2021.01.16 |
Hunk # 1 FAILED at 1 그게 무슨 뜻입니까? (0) | 2021.01.15 |