2011-08-24 3 views
24

다음과 같은 코드가 있습니다 :평등을 두 번 확인하는 것이 안전할까요?

double x = 0; 

{ ...do stuff ...} 

if(x == 0){ 

} 

항상 평등을 위해 수레를 점검해서는 안된다는 것을 배웠습니다. 0과 같지 않은지 확인하고 있습니까?

+0

init x 값을 0으로 설정하면 0인지 확인하는 것이 좋지 않은 이유는 무엇입니까? 0은 double에 대한 유효한 값입니다. – JohnJohnGa

+1

한계에 도달하기 시작하면 부동 소수점 숫자에 많은 반올림이 있습니다. 같은 이유로 10 진수로 3 자릿수를 사용하면 .004를 가지며 3으로 나누면 .001을 기대하지만 누가 무슨 일이 일어나는 지 알 수 있습니다. –

+0

Thomas의 교정 : 기술적으로는 반올림하지 않지만 부동 소수점의 정밀도와 이진 특성으로 인해 정확성이 떨어집니다. –

답변

27

부동 소수점 수를 확인하지 않아야하는 이유는 부동 소수점 숫자가 완벽하게 정확하지 않기 때문입니다. 가수로 너무 길어서 소수점을 반복하는 것과 같이 일부 숫자가있는 저장에서는 정확하지 않습니다. 저는베이스 2에서 소수를 반복하는 것에 대해 이야기하고 있습니다.) 이 부정확성은 "반올림"이라고 생각할 수 있습니다. 부동 소수점 숫자의 정밀도 이상으로 확장되는 자릿수는 잘리고 잘립니다.

변경되지 않은 경우 해당 동등성이 유지됩니다. 그러나 조금이라도 변경하면 평등을 사용하지 말고 (x < 0.0001 && x > -.0001)과 같은 범위를 사용해야합니다.

간단히 말해서, 아주 작은 레벨에서 x로 놀지 않는 한 괜찮습니다.

+6

그것은 계속 진행 중이지만 부동 소수점 숫자로 인해 특정 숫자를 저장할 수 없다는 것을 의미합니다. 0은 부동 소수점 값으로 정확하게 나타낼 수 있지만 모든 값을 표현할 수는 없습니다. 예를 들어, 0.1을 근사화해야합니다. –

+1

@ 토마스 반올림. '3/2'가 '1'과 같은 이유 –

+7

아니요, 반올림하지 않습니다. IEEE 부동 소수점 표현의 부정확성. 반올림과 전혀 관련이 없습니다. http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems –

16

잡으려고하는 것이 초기화시 원래 0 세트이면 안전합니다. 그러나 수학 연산에서 0을 기대한다면 안전하지 않습니다.

+0

수학 연산에서 0을 비교하고자 할 때 올바른 접근 방식이되어야합니다. –

+0

허용되는 대답을 참조하십시오. – Vache

4

여전히 0이 아닌지 확인하지 않아야합니다. 그것이 0에 가까운 지 확인하십시오.

private final static double EPSILON = 0.00001; 
if (x + EPSILON > 0 && x - EPSILON < 0){ 
... 
} 
+3

절대적인 에피소드는 사용하지 말고 절대적으로 사용하십시오. 만약 값이 넓은 범위에서 변할 수있는 경우에 특히 그렇습니다. "예를 들어, (value) = target * (1- 엡실론) && value <= target * (1 + 엡실론) –

+2

@HovercraftFullOfEels이 옵션은 대상이 양수인 경우에만 작동합니다. –

4

당신은 스스로를 설정하고 NaN이 그

float x=Float.NaN; 
{ 
    //some code that may or may not set x 
} 
if(Float.isNaN(x))//it never got set 
2

같은 것들에 대한 안전하지만 그것도 (센티넬 값을 사용하여 같은) 안전하게 어떤지를 확인하실 수 있습니다 변경 있는지 확인하고자하는 경우 이중있다 양수 및 음수 0 긍정 0과 음수 0 사이의 ==은 false를 반환합니다. 또한 두 개의 NaN 사이의 ==은 false를 반환합니다.

관련 문제