C ++如何计算复数的绝对值,防止溢出?

时间:2016-12-09 16:12:08

标签: c++ numeric floating-accuracy complex-numbers

C ++标题<complex>提供abs(z)norm(z)

复数z = x + iy的范数是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;
}

输出:

5e+200 -> 0
inf -> 1

1 个答案:

答案 0 :(得分:2)

std::complex::abs等同于std::hypot函数,确实可以保证在计算的中间阶段避免溢出和下溢。

Wikipedia page on Hypot function提供了有关实施的一些见解。

我将引用伪代码以防万一:

  // hypot for (x, y) != (0, 0)
double hypot(double x,double y)
{
    double t;
    x = abs(x);
    y = abs(y);
    t = min(x,y);
    x = max(x,y);
    t = t/x;
    return x*sqrt(1+t*t);
}