IT이야기

0에 가까운 부동값이 있으면 0으로 나누기 오류가 발생할 수 있습니까?

cyworld 2022. 7. 24. 22:28
반응형

0에 가까운 부동값이 있으면 0으로 나누기 오류가 발생할 수 있습니까?

플로트를 직접 비교하는 것이 아니라 공차를 사용해야 한다는 것은 누구나 알고 있습니다.

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?

이 경우에도 엡실론과 비교해야 합니까?

부동소수점 나눗셈은 오류가 아닙니다.부동소수점 예외를 지원하는 구현에서 부동소수점 예외(액티브하게 체크하지 않는 한 no-op)를 발생시켜 양의 무한대(분자가 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 미만인-126 제로 이외의 수치입니다.배정밀의 경우 진도 2보다 작은-1022 0이 아닌 숫자입니다.

(IEEE 754에 준거한) 정규 이하의 수치를 올바르게 처리하려면 , 일부의 프로세서에서 추가의 연산 시간이 필요합니다.이 지연을 피하기 위해 프로세서는 정상 이하의 오퍼랜드를 0으로 변환하는 모드를 사용할 수 있습니다.숫자를 정규 이하의 오퍼랜드로 나누면 일반 결과가 유한하더라도 0으로 나누는 것과 같은 결과가 됩니다.

다른 답변에서 언급한 바와 같이, 0으로 나누는 것은 C 표준의 Annex F를 채택한 C 구현에서 오류가 아니다.모든 구현이 가능한 것은 아닙니다.그렇지 않은 구현에서는 환경에 대한 추가 지정이 없으면 부동소수점 트랩, 특히 제로 분할 예외 트랩이 활성화되었는지 여부를 확인할 수 없습니다.

상황에 따라서는 부동소수점 환경을 변경하는 어플리케이션의 다른 코드를 주의해야 할 수도 있습니다.

게시물의 제목에 있는 질문에 답하기 위해 아주 작은 숫자로 나누면 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이 됩니다.0.0f는 IEEE 플로트로 정확하게 표시됩니다.

다만, 어느 정도의 허용치를 사용하고 싶다고 하는 것은, 사용의 애플리케이션에 의해서 다릅니다."0" 값이 다른 산술의 결과일 경우 0이 아닌 매우 작은 숫자를 얻을 수 있으며, 이는 나눗셈 후에 예상치 못한 결과를 초래할 수 있습니다."0에 가까운" 숫자를 0으로 처리하려면 공차가 적절합니다.단, 이는 어플리케이션과 목표에 따라 완전히 달라집니다.

사용의 컴파일러가 예외 처리에 IEEE 754 표준을 사용하고 있는 경우는, 0으로 나눗셈하는 것과 동시에, 오버플로를 일으킬 수 있는 작은 값으로 나눕니다.둘 다 +/-infiniti 값이 됩니다.즉, 매우 작은 숫자에 대한 체크를 포함할 수 있습니다(플랫폼에 오버플로가 발생할 수 있음).예를 들어 Windows의 경우,float그리고.double둘 다 규격을 준수하므로 0과 같이 매우 작은 제수가 +/- 무한대를 생성할 수 있습니다.

사용하시는 컴파일러/플랫폼이 IEEE 754 부동소수점 표준에 준거하고 있지 않은 경우는 플랫폼 고유의 결과라고 생각합니다.

언급URL : https://stackoverflow.com/questions/12114498/can-a-near-zero-floating-value-cause-a-divide-by-zero-error

반응형