2010-02-06 2 views
7

가능한 중복 : 나는 몇 가지 숫자와 C# 및 다른 수의 코드 결과의 다음 줄 다루고있다
Why is floating point arithmetic in C# imprecise?이상한 결과 때 빼서 두 배

한 것보다 더 기대 :

double num = (3600.2 - 3600.0); 

을 내가 NUM 0.2 것으로 예상하지만, 그것은 밝혀졌다 0.1999999999998181. 가까운, 그러나 여전히 다른 소수를 생산하는 이유가 있습니까?

+0

허, 여기와 동일. 당신의 기계가 아닙니다. – tsilb

+2

http://stackoverflow.com/questions/1498296/net-problem-with-subtracting-double-values ​​ –

+2

http://stackoverflow.com/questions/753948/why-is-floating-point-arithmetic-in-c -imprecise –

답변

10

double은 부동 소수점 데이터 유형이기 때문입니다.

정확성을 높이려면 decimal을 대신 사용할 수 있습니다.

decimal의 문자 접미사 그래서 당신은 decimal를 사용하는 단점이 있다는 것을

var num = (3600.2m - 3600.0m); 

참고로 코드를 작성할 수 decimal 연산을 사용 (그리고 decimal 결과를 생성)을, m이다. double의 크기 인 64 비트가 아니라 128 비트 데이터 유형입니다. 따라서 메모리와 처리 측면에서 비용이 많이 듭니다. 또한 double보다 훨씬 작은 범위가 있습니다.

+2

이것은 무한 정밀도가 아니라면 얼마나 많은 정밀도를 갖는지와 아무런 관련이 없습니다. 이것을 만드는 한 기지에서 다른 기지로의 전환입니다. – AraK

+6

IEEE 754 유형에 관한 잘못된 정보는 언제 중단됩니까? 그것은 정확하지 않은 타입이 아닙니다! 정확한 유형이지만 숫자의 제한된 범위 만 나타낼 수 있습니다. 정확하게 표현되지 않은 모든 숫자는 근사값이며 이는 오류의 원인입니다. 유형의 범위 내에서 2의 제곱 수를 나타내려면 부동 소수점으로 정확성을 잃지 마십시오. – codekaizen

+1

@AdamRalph - Decimal에 대해서는 사실이 아닙니다. System.Decimal은 부동 소수점 유형이지만 기본 10에 있으므로 일반적인 10 진수가 적용됩니다. 그러나 1/3로 계산 해보면 Decimal은 정확성을 잃어 버리게되지만 96 비트 가수에서는 System.Double보다 훨씬 적은 손실이 발생합니다. – codekaizen

0
decimal으로 유형을 변경

:

decimal num = (3600.2m - 3600.0m); 

는 또한 this을 읽어야합니다.

1

이유가 있습니다.

이유는 숫자가 메모리에 저장되는 방식이 이중 데이터 유형의 경우 숫자 3600.2의 정확한 표현을 허용하지 않기 때문입니다. 또한 숫자 0.2의 정확한 표현을 허용하지 않습니다.

0.2는 2 진수로 무한대로 표현됩니다. 메모리 또는 프로세서 레지스터에 저장하려면 계산을 수행하기 위해 유한 표현으로 0.2에 가까운 숫자가 대신 저장됩니다. 이런 코드를 실행하면 분명하지 않을 수 있습니다.

double num = (0.2 - 0.0); 

이 경우, Double 데이터 형식의 숫자를 표현하기위한 가능한 모든 이진수가 (단지 소수 부분이) 숫자의 소수 부분을 표현하기 위해 사용되며, 정밀도가 높은 때문입니다. 3600.2라는 숫자를 double 유형의 객체에 저장하면 일부 숫자가 정수 부분을 나타내는 데 사용됩니다 (3600). 분수 부분을 나타내는 숫자가 적습니다. 실제로 정밀도가 낮고 메모리에 실제로 저장된 소수부는 0.2에서 충분하지 않아 두 배에서 문자열로 변환 한 후 분명해진다.