C++ 헤더 <complex>
은 abs(z)
과 norm(z)
을 제공합니다.C++은 어떻게 오버플로를 방지하면서 복소수의 절대 값을 계산합니까?
복소수 z = x + iy의 norm은 norm(z)
: = x^2 + y^2입니다.
z의 절대 값은 abs(z)
: = sqrt (norm (z))입니다.
그러나 다음 예제에서는 abs(z)
이 다르게 구현되어야 함을 보여줍니다. norm(z)
이 오버플로하지 않기 때문에. 적어도 g ++ 6.2.1에서는 오버플로가 발생하지 않습니다.
표준에 따라 오버플로가 보장되지 않습니까? 그것은 어떻게 성취됩니까?
#include <iostream>
#include <complex>
typedef std::complex<double> complex_t;
int main()
{
complex_t z = { 3e200, 4e200 };
double a = abs(z);
double n = norm(z);
std::cout << a << " -> " << std::isinf(a) << "\n";
std::cout << n << " -> " << std::isinf(n) << "\n";
return 0;
}
출력 : std::complex::abs
실제로 계산의 중간 단계에서 오버 플로우와 언더 플로우를 방지하도록 보장 std::hypot
함수에 상당
5e+200 -> 0
inf -> 1
봐. 적어도 내 시스템에서는 abs (실수 부분), abs (imag 부분)의 최대 값을 먼저 나눈 다음 곱합니다. 이는 오버 플로우가 발생하지 않는 이유 일 수 있습니다. –
libstdC++와 다른 점이 있습니다 :'abs'에 대한 계산은 direct ([source] (https://code.woboq.org/gcc/libstdc++-v3/include/std/complex.html#572)입니다.)), norm에 대한 계산은 절대 값 ([source] (https://code.woboq.org/gcc/libstdc++-v3/include/std/complex.html#652))을 제곱합니다. Abs는 또한 실제 부분과 허수 부분을 최대로 나누었습니다. 아마도 오버플로를 방지하기 위해서입니다. – peppe