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

How does C++ compute the absolute value of a complex number, preventing overflow?

本文关键字:绝对值 溢出 何计算 计算      更新时间:2023-10-16

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

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

Hypot功能上的Wikipedia页面提供了有关实现的一些见解。

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

  // 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);
}