0에 가까운 부동 값이 0으로 나누기 오류를 일으킬 수 있습니까?
모두가 float를 직접 비교하는 것이 아니라 허용 오차를 사용하여 비교해야한다는 것을 알고 있습니다.
float a,b;
float epsilon = 1e-6f;
bool equal = (fabs(a-b) < epsilon);
나눗셈에서 사용하기 전에 값을 0과 비교하는데도 똑같이 적용되는지 궁금합니다.
float a, b;
if (a != 0.0f) b = 1/a; // oops?
이 경우에도 엡실론과 비교해야합니까?
0으로 부동 소수점을 나누는 것은 오류가 아닙니다. 부동 소수점 예외를 지원하고 잘 정의 된 결과 : 양수 또는 음수 무한대 (분자가 0이 아닌 경우)를 갖는 구현에서 부동 소수점 예외 (적극적으로 확인하지 않는 한 작동하지 않음)를 발생시킵니다. NAN (분자가 0 인 경우).
또한 분모가 0이 아니지만 0에 매우 가까울 때 (예 : 비정규) 결과로 무한대 (및 오버플로 예외)를 얻을 수도 있지만 이는 다시 오류가 아닙니다. 부동 소수점이 작동하는 방식입니다.
편집 : Eric이 의견에서 지적 했듯이이 답변은 부동 소수점 동작을 자세히 설명하고 부동 소수점에 대한 IEEE 표준과 정렬하는 C 표준의 선택적 부분 인 Annex F의 요구 사항을 가정합니다. IEEE 산술이없는 경우 C는 부동 소수점 나누기를 0으로 정의하지 않습니다 (실제로 모든 부동 소수점 연산의 결과는 구현에 따라 정의되고 완전한 넌센스로 정의 될 수 있으며 여전히 C 표준을 준수 함). IEEE 부동 소수점을 따르지 않는 이상한 C 구현을 다루고 있습니다.이 질문에 답하기 위해 사용중인 구현에 대한 문서를 참조해야합니다.
예, 작은 숫자로 나누면 일부 상황에서 트랩을 포함하여 0으로 나누는 것과 동일한 효과가 발생할 수 있습니다.
일부 C 구현 (및 일부 다른 컴퓨팅 환경)은 특히 고성능 옵션이 사용되는 경우 플러시 언더 플로 모드에서 실행될 수 있습니다. 이 모드에서 비정규로 나누면 0으로 나누는 것과 같은 결과가 나올 수 있습니다. 벡터 (SIMD) 명령어가 사용되는 경우 플러시 언더 플로우 모드는 드물지 않습니다.
비정규 숫자는 부동 소수점 형식에서 최소 지수를 가진 숫자로, 유효 숫자의 암시 적 비트가 1이 아닌 0이 될 수 있습니다. IEEE 754의 경우 단 정밀도, 크기가 2 미만인 0이 아닌 숫자입니다. -126 . 배정 밀도의 경우 크기가 2 -1022 미만인 0이 아닌 숫자입니다 .
비정규 숫자를 올바르게 처리 (IEEE 754에 따라)하려면 일부 프로세서에서 추가 컴퓨팅 시간이 필요합니다. 필요하지 않을 때 이러한 지연을 피하기 위해 프로세서는 비정규 피연산자를 0으로 변환하는 모드를 가질 수 있습니다. 숫자를 비정규 피연산자로 나누면 일반적인 결과가 유한하더라도 0으로 나누는 것과 동일한 결과가 생성됩니다.
다른 답변에서 언급했듯이 0으로 나누는 것은 C 표준의 Annex F를 채택하는 C 구현에서 오류가 아닙니다. 그렇게하는 모든 구현이 아닙니다. 그렇지 않은 구현에서는 사용자 환경에 대한 추가 사양없이 부동 소수점 트랩, 특히 0으로 나누기 예외에 대한 트랩이 활성화되었는지 여부를 확인할 수 없습니다.
상황에 따라 부동 소수점 환경을 변경하는 응용 프로그램의 다른 코드로부터 보호해야 할 수도 있습니다.
게시물 제목의 질문에 답하기 위해 아주 작은 숫자로 나누면 0으로 나누지는 않지만 결과가 무한대가 될 수 있습니다.
double x = 1E-300;
cout << x << endl;
double y = 1E300;
cout << y << endl;
double z = y / x;
cout << z << endl;
cout << (z == std::numeric_limits<double>::infinity()) << endl;
그러면 다음과 같은 출력 이 생성됩니다 .
1e-300
1e+300
inf
1
정확히 0.f로 나누면 0으로 나누기 예외가 발생합니다.
그러나 정말 작은 숫자로 나누면 오버플로 예외가 발생할 수 있습니다. 결과가 너무 커서 더 이상 부동 소수점으로 표현할 수 없습니다. 분할은 무한대를 반환합니다.
무한대의 부동 표현은 계산에 사용할 수 있으므로 나머지 구현에서 처리 할 수 있는지 확인할 필요가 없습니다.
이 경우에도 엡실론과 비교해야합니까?
IEEE float0.0f
에서 정확히 표현 되는 것처럼 0으로 나누기 오류가 발생하지 않습니다 .
그러나 이는 전적으로 응용 프로그램에 따라 다르지만 여전히 약간의 허용 오차를 사용하고 싶을 수 있습니다. "0"값이 다른 수학의 결과 인 경우 0이 아닌 매우 작은 숫자를 얻을 수 있으며, 이로 인해 나눗셈 후에 예기치 않은 결과 가 발생할 수 있습니다 . "0에 가까운"숫자를 0으로 처리하려면 허용 오차가 적절합니다. 그러나 이것은 전적으로 귀하의 응용 프로그램과 목표에 달려 있습니다.
If your compiler is using IEEE 754 standards for exception handling, then divide by zero, as well as a division by a value which is small enough to cause an overflow, would both result in a value of +/- infiniti. This could mean that you could want to include the check for very small numbers (that would cause an overflow on your platform). For example, on Windows, float
and double
both conform to the specifications, which could cause a very small divisor to create +/- infiniti, just like a zero value.
If your compiler/platform is not following IEEE 754 floating point standards, then I believe the results are platform specific.
'IT박스' 카테고리의 다른 글
Git이 파일을 감지하지 못하고 .gitignore에 없습니다. (0) | 2020.12.08 |
---|---|
캔버스를 부모만큼 넓고 높이 만들기 (0) | 2020.12.08 |
Rails 콘솔을 사용하여 테이블에서 열을 제거하는 방법 (0) | 2020.12.08 |
채널을 읽지 않고 닫혔는지 여부를 확인하는 방법은 무엇입니까? (0) | 2020.12.08 |
패키지 버전을 setup.py 및 패키지와 공유하는 올바른 방법은 무엇입니까? (0) | 2020.12.08 |