2016-12-09 12 views
3

В заголовке C++ <complex> приведены abs(z) и norm(z).Как C++ вычисляет абсолютное значение комплексного числа, предотвращая переполнение?

Нормой комплексного числа 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

Посмотрите на реализацию в заголовочном файле. По крайней мере, на моей системе максимальный абс (действительная часть), абс (часть воображения) используется для первого разделения, затем умножается. Это может быть причиной отказа от переполнения. –

+1

Похоже, что libstdC++ делает это наоборот: вычисление 'abs' является прямым ([source] (https://code.woboq.org/gcc/libstdc++-v3/include/std/complex.html#572)), вычисление для нормы умножает абсолютное значение ([источник] (https://code.woboq.org/gcc/libstdc++-v3/include/std/complex.html#652)). Абс также разделял как реальные, так и мнимые части по максимуму, вероятно, чтобы предотвратить переполнение. – peppe

ответ

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); 
} 
+1

Jut отметить, что это не совсем то, что сделает libm. Эта реализация не даст 1ULP ошибки –

+1

@YanZhou о да, точно, этот псевдокод не то, что происходит вообще; однако это объясняет ситуацию переполнения. «Реальный код» будет похож на [this] (https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/ieee754/dbl-64/e_hypot.c) – Ap31

 Смежные вопросы

  • Нет связанных вопросов^_^