В заголовке 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
Посмотрите на реализацию в заголовочном файле. По крайней мере, на моей системе максимальный абс (действительная часть), абс (часть воображения) используется для первого разделения, затем умножается. Это может быть причиной отказа от переполнения. –
Похоже, что 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