문제

난에 의존할 수는 없습 사이의 평등 더블룸 또는 소수 입력 값은 일반적으로,하지만 내가 궁금하는 경우 0 은 특별한 경우이다.

는 동안 내가 이해할 수 있 imprecisions 사 0.00000000000001 및 0.00000000000002,0 마 열심히 엉망 이후 그냥 아무것도 아니다.만약 당신이 정확하지 않기에 아무것도,그것은 아무것도하지 않습니다 더 이상.

지에 대해 많이 알고 이제 그래서 그것이 나를 말한다.

double x = 0.0;
return (x == 0.0) ? true : false;

이 항상 반품이 사실인가?

도움이 되었습니까?

해결책

그것은이다 안전한 비교가 돌아올 것으로 기대합니다 true 이중 변수의 값이 정확히있는 경우에만 0.0 (원래 코드 스 니펫에서는 물론 그렇습니다). 이것은 의미의 의미와 일치합니다 == 운영자. a == b 수단 "a 와 동등하다 b".

그것은이다 안전하지 않음 (이 때문에 정확하지 않습니다) 순수한 수학에서 동일한 계산 결과가 0 일 때마다 일부 계산 결과가 2 배 (또는 더 일반적으로 부동 소수점) 산술로 될 것으로 예상합니다. 계산이지면에 들어올 때 부동 소수점 정밀 오류가 나타나기 때문입니다. 수학의 실수 산술에는 존재하지 않는 개념이 있습니다.

다른 팁

"평등"비교를 많이 해야하는 경우 .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은 이진에서 반복되는 소수점이며 정확히 표현할 수 없다는 것을 기억하십시오. 그런 다음이 코드와 비교하십시오.

double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away
bool b = ( d1 - 1.0 == 0.0 );

실제 결과를보기 위해 테스트를 실행하도록하겠습니다. 그런 식으로 기억할 가능성이 더 높습니다.

MSDN 항목에서 double.equals:

비교의 정밀도

두 값의 정밀도로 인해 두 개의 명백한 동등한 값이 불평등 할 수 있기 때문에 평등 방법은주의해서 사용해야합니다. 다음 예제는 이중 값 .3333과 1을 3으로 나누어 반환 된 이중 값이 불평등하다고보고합니다.

...

평등을 비교하는 대신, 권장되는 하나의 권장 기술은 두 값 (예 : 값 중 하나의 .01%) 사이의 수용 가능한 차이 마진을 정의하는 것이 포함됩니다. 두 값 사이의 차이의 절대 값이 그 여백보다 작거나 같으면 차이는 정밀도의 차이로 인한 것일 수 있으므로 값이 동일 할 수 있습니다. 다음 예제는이 기술을 사용하여 .33333과 1/3을 비교합니다. 이전 코드 예제가 불평등 한 두 가지 이중 값입니다.

또한 참조하십시오 Double.epsilon.

문제는 다른 유형을 비교하의 부동 소수점의 값을 구현 예:비교 부동으로 두 배.하지만 같은 형식,그것은 문제가 안 된다.

float f = 0.1F;
bool b1 = (f == 0.1); //returns false
bool b2 = (f == 0.1F); //returns true

문제,프로그래머로 잊는다는 암시적인 형식이 캐스팅(두 배를 떠)일이 일어나고 있을 비교하고 그 결과로 버그입니다.

숫자가 플로트에 직접 할당되거나 두 배의 숫자를 두 배나 24 비트로 53 비트로 표현할 수있는 정수에 대해 테스트하는 것이 안전합니다.

또는 다른 방법으로 값을 할당하고 정수 값을 이중으로 할당하고 이중을 동일한 정수와 비교하고 동일하게 보장됩니다.

또한 정수를 할당하여 시작할 수 있으며 정수를 추가, 빼기 또는 곱하면 간단한 비교가 계속 작동합니다 (결과는 플로트 ABD 53 비트의 경우 24 비트 미만이라고 가정). 따라서 특정 통제 조건에서 수레와 복식을 정수로 취급 할 수 있습니다.

아니요, 괜찮지 않습니다. 0.0과 비교할 때 소위 탈피 된 값 (subnormal)은 거짓 (0이 아닌)과 비교할 수 있지만 방정식에 사용될 때는 정규화됩니다 (0.0이됩니다). 따라서 이것을 제로별로 분할을 피하기위한 메커니즘으로 사용하는 것은 안전하지 않습니다. 대신 1.0을 추가하고 1.0과 비교하십시오. 이렇게하면 모든 아대형이 0으로 처리되도록합니다.

이것을 시도하면 ==가 더블/플로트에 대해 신뢰할 수 없다는 것을 알게 될 것입니다.
double d = 0.1 + 0.2; bool b = d == 0.3;

여기에 있습니다 대답 Quora에서.

실제로 다음 코드를 사용하여 이중 값을 0.0으로 비교하는 것이 좋습니다.

double x = 0.0;
return (Math.Abs(x) < double.Epsilon) ? true : false;

플로트에 대해서도 마찬가지 :

float x = 0.0f;
return (Math.Abs(x) < float.Epsilon) ? true : false;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top