2012-07-02 3 views
8

무엇이 1.#INF이고 왜 캐스팅이 float 또는 double 인 경우 0의 충돌로 인한 충돌을 방지 할 수 있습니까?
또한 0으로 나누는 것을 방지하는 방법에 대한 훌륭한 아이디어가 있습니까? (매크로 또는 템플릿과 마찬가지로)?제로 방지로 나누기

int nQuota = 0; 

int nZero = 3/nQuota; //crash 
cout << nZero << endl; 

float fZero = 2/nQuota; //crash 
cout << fZero << endl; 

내가 대신 사용하는 경우 :

int nZero = 3/(float)nQuota; 
cout << nZero << endl; 
//Output = -2147483648 

float fZero = 2/(float)nQuota; 
cout << fZero << endl; 
//Output = 1.#INF 
+2

와우 흥미로운. 답변을 기대합니다. –

+0

이것은 흥미로울 것입니다 : http://blog.regehr.org/archives/721 – cppanda

답변

12

1.#INF은 무한대입니다. 양수 부동 소수점을 0으로 나눌 때 얻을 수 있습니다 (부동 소수점 0을 0으로 나누면 결과는 "숫자가 아님"이됩니다).

정수를 0으로 나누면 프로그램이 중단됩니다.

이유가 float fZero = 2/nQuota; 인 경우 / 연산자의 두 피연산자 모두 정수이므로 나누기가 정수로 수행되기 때문입니다. 결과를 float에 저장하는 것은 중요하지 않습니다. C++에는 표적 타이핑에 대한 개념이 없습니다.

정수로의 양의 무한대가 가장 작은 정수인 이유는 무엇입니까?

+0

무엇에 대해 -2147483648? –

+1

-2147483648은 1입니다. # INF는 정수로 변환됩니다. –

+3

C 스펙은'NaN' 또는 무한 float 값을 정수로 변환 한 결과를 지정하는 것으로 나타나지 않습니다. "부동 소수점 값이 무한하거나 NaN이거나 부동 소수의 정수 부분이 정수 유형의 범위를 초과하는 경우"유효하지 않은 "부동 소수점 예외가 발생하고 결과 값이 지정되지 않습니다." – mkb

1

일반적으로 0으로 나누지 않았는지 확인하십시오. nQuota 합법적 인 값을 가지고 있지만 충돌의 0으로 나누기 (플로트) 또는 (더블)을 방지하여 충돌

int nQuota = 0; 
int nZero = 0; 
float fZero = 0; 
if (nQuota) 
    nZero = 3/nQuota; 
cout << nZero << endl; 

if (nQuota) 
    fZero = 2/nQuota; 
cout << fZero << endl; 
+0

간단하지만 그 매력과 비슷합니다. –

3

Wwhy을 방지 않습니다하지 않는 한 아래의 코드는 특히 유용하지 않다?

반드시 그렇지는 않습니다. 부동 소수점에 관해서 표준은 놀랍습니다. 대부분의 시스템은 요즘 IEEE 부동 소수점 표준을 사용합니다. 즉, 0으로 나누기위한 기본 동작은 충돌보다는 ± 무한대를 반환하는 것입니다. 적절한 부동 소수점 예외를 사용하면 충돌을 일으킬 수 있습니다.

참고 : 부동 소수점 예외 모델과 C++ 예외 모델은 공통적으로 "예외"라는 단어 만 사용합니다. 내가 작업하는 모든 컴퓨터에서 부동 소수점 예외가 C++ 예외를 throw하지 않습니다.

또한 0으로 나누는 것을 방지하는 방법에 대한 훌륭한 아이디어가 있습니까?

  1. 간단한 대답은 :하지 마십시오.
    이것은 "의사 선생님, 제가 이럴 때 의사가 아파요!" 상황의 종류. 그러지 마라.

  2. 제수가 0이 아닌지 확인하십시오.
    사용자 입력 인 약수에 대한 온 전성 검사를 수행하십시오. 항상 사용자 입력을 필터링하여 정상 성을 유지하십시오. 번호가 수백만에있을 때 사용자 입력 값이 0이면 오버플로 외에도 모든 종류의 혼란이 발생합니다. 중간 값에 대한 온 전성 검사를 수행합니다.

  3. 부동 소수점 예외 사용.
    오류를 허용하는 기본 동작 (그리고 거의 항상 오류)을 선택하지 않는 것은 IMHO가 표준위원회의 큰 실수였습니다.기본값과 무한대를 사용하면 숫자가 아닌 숫자가 결국 모든 것을 Inf 또는 NaN으로 변환합니다.
    기본값은 1.0/0.0 및 0.0/0.0과 같은 항목을 허용하는 옵션을 사용하여 트랙에서 부동 소수점 오류를 중지해야합니다. 그런 경우가 아니므로 해당 트랩을 활성화해야합니다. 그렇게하면 자주 문제의 원인을 짧은 시일 내에 발견 할 수 있습니다.

  4. 사용자 정의 나누기, 사용자 정의 곱하기, 사용자 정의 제곱근, 사용자 정의 사인 ... ... 함수를 작성하십시오.
    이것은 안타깝게도 많은 안전에 중요한 소프트웨어 시스템이 취해야하는 경로입니다. 그것은 왕의 고통입니다. 옵션 # 1은 소원 성의 사고이기 때문에 빠져 있습니다. 옵션 # 3은 시스템이 충돌을 허용 할 수 없기 때문에 꺼져 있습니다. 옵션 # 2는 여전히 좋은 생각이지만 나쁜 데이터는 항상 몰래 들어가는 방법이 있기 때문에 항상 효과가있는 것은 아닙니다. 머피의 법칙입니다.

참고 : 문제는 0으로 나누는 것보다 약간 나쁩니다. 10/10 -200도 오버 플로우됩니다.