일반적으로 double 또는 decimal 유형 값 사이의 평등에 의존 할 수 없다는 것을 알고 있지만 0이 특별한 경우인지 궁금합니다.
0.00000000000001과 0.00000000000002 사이의 부정확성을 이해할 수 있지만 0 자체는 아무것도 아니기 때문에 엉망이되기가 꽤 어렵습니다. 아무것도 정확하지 않다면 더 이상 아무것도 아닙니다.
하지만 저는이 주제에 대해 잘 모르기 때문에 제가 말할 것도 없습니다.
double x = 0.0;
return (x == 0.0) ? true : false;
그게 항상 사실로 돌아 올까요?
답변
double 변수에 정확히 값이있는 경우에만 비교 결과가 반환 될 것으로 예상하는 것이 안전 합니다 (원래 코드 스 니펫에서는 물론 해당됨). 이것은 연산자 의 의미와 일치합니다 . ” 는 ” 와 같다는 의미 입니다.true
0.0
==
a == b
a
b
그것은이다 안전하지 (이 때문에 정확하지 ) 일부 계산의 결과가 순수 수학에서 같은 계산의 결과가 0 때마다 두 배 (또는 더 일반적으로, 부동 소수점)를 arithmetics 제로가 될 것으로 기대합니다. 그 이유는 계산이 시작되면 부동 소수점 정밀도 오류가 나타나기 때문입니다. 이는 수학의 실수 산술에는 존재하지 않는 개념입니다.
답변
“동등”비교를 많이해야하는 경우 비교를 위해 .NET 3.5에서 약간의 도우미 함수 또는 확장 메서드를 작성하는 것이 좋습니다.
public static bool AlmostEquals(this double double1, double double2, double precision)
{
return (Math.Abs(double1 - double2) <= precision);
}
다음과 같은 방법으로 사용할 수 있습니다.
double d1 = 10.0 * .1;
bool equals = d1.AlmostEquals(0.0, 0.0000001);
답변
간단한 샘플의 경우 해당 테스트는 괜찮습니다. 하지만 이것에 대해 :
bool b = ( 10.0 * .1 - 1.0 == 0.0 );
.1은 이진수로 반복되는 10 진수이며 정확하게 표현할 수 없습니다. 그런 다음 다음 코드와 비교하십시오.
double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away
bool b = ( d1 - 1.0 == 0.0 );
실제 결과를 확인하기 위해 테스트를 실행하도록 남겨 둘 것입니다. 그렇게 기억할 가능성이 더 큽니다.
답변
Double.Equals에 대한 MSDN 항목에서 :
비교 정밀도
Equals 메서드는 두 값의 정밀도가 다르기 때문에 분명히 동일한 두 값이 같지 않을 수 있으므로주의해서 사용해야합니다. 다음 예제에서는 Double 값 .3333과 1을 3으로 나누어 반환 된 Double이 같지 않다고보고합니다.
…
동등성을 비교하는 대신 권장되는 한 가지 기술은 두 값 간의 허용 가능한 차이 한계를 정의하는 것입니다 (예 : 값 중 하나의 .01 %). 두 값 간의 차이의 절대 값이 해당 여백보다 작거나 같으면 차이는 정밀도 차이로 인한 것일 수 있으므로 값이 같을 가능성이 있습니다. 다음 예제에서는이 기술을 사용하여 이전 코드 예제에서 같지 않은 것으로 확인 된 두 Double 값인 .33333과 1/3을 비교합니다.
또한 Double.Epsilon을 참조하십시오 .
답변
문제는 부동 소수점 값 구현의 다른 유형을 비교할 때 발생합니다 (예 : float와 double 비교). 하지만 같은 타입이라면 문제가되지 않습니다.
float f = 0.1F;
bool b1 = (f == 0.1); //returns false
bool b2 = (f == 0.1F); //returns true
문제는 프로그래머가 때때로 암시 적 유형 캐스트 (double to float)가 비교를 위해 발생하고 그 결과 버그가 발생한다는 사실을 잊어 버리는 것입니다.
답변
숫자가 float 또는 double에 직접 할당 된 경우 0 또는 double의 경우 53 비트로, float의 경우 24 비트로 나타낼 수있는 정수에 대해 테스트하는 것이 안전합니다.
또는 다른 방법으로 말하면 항상 double에 정수 값을 할당 한 다음 double을 동일한 정수와 다시 비교하여 동일하다는 것을 보장 할 수 있습니다.
정수를 할당하여 시작하여 정수를 더하거나 빼거나 곱하는 방식을 고수하여 간단한 비교를 계속할 수 있습니다 (결과가 float abd의 경우 24 비트 미만이라고 가정하면 double의 경우 53 비트). 따라서 특정 제어 조건에서 float 및 double을 정수로 처리 할 수 있습니다.
답변
아니요, 괜찮지 않습니다. 소위 비정규 화 된 값 (비정규 화)은 0.0과 비교 될 때 거짓 (0이 아님)으로 비교되지만 방정식에 사용되면 정규화 (0.0이 됨)가됩니다. 따라서 이것을 0으로 나누는 것을 방지하는 메커니즘으로 사용하는 것은 안전하지 않습니다. 대신 1.0을 더하고 1.0과 비교하십시오. 이렇게하면 모든 비법 선이 0으로 처리됩니다.