abs () возвращает отрицательное значение для некоторых очень больших двойных значений

Я работал с некоторыми большими двойными значениями, и все математические функции были в порядке. Кажется, что sqrt, pow и другие математические функции не имеют проблем с большими научными двойными значениями, но abs не может обработать эти числа.
например, это нормально:

double s = sqrt(3.9 * 1e32);

но это не так:

double s = sqrt(abs(3.9 * 1e32));

потому что abs возвращает отрицательное значение;
Я не понимаю, почему эта простая функция не может обрабатывать научные двойные операции, когда все эти сложные работают нормально. Я что-то упустил или это действительно так, и я не могу использовать функцию c ++ abs для таких значений?

MCVE

#include <cstdlib>
#include <cstdio>

int main()
{
double d = 3.9e32;
double f = abs(d);

std::printf("%f\n", f);
}

Результаты

  • Coliru: 2147483647.000000
  • g ++ 4.8.3-cygwin: -2147483648.000000

В этом MCVE меняется abs в std::abs вызывает ошибку компиляции из-за ошибки разрешения перегрузки (не может выбирать между std::abs<int>, std::abs<long>, std::abs<long long>).

2

Решение

Проблема в том, что вы используете abs(int) когда ты нуждаешься fabs(double) или лучше в C ++, std::abs(), Вы сказали, что пытались std::abs(), но если бы у вас было, это бы решило вашу проблему.

Это печальная и распространенная ловушка в C ++. Никогда не используйте abs() без std:: на передней. Это опасно.

4

Другие решения

Утверждение, что abs вернуть int в C ++ упоминается в других ответах совершенно неверно. В C ++ стандартная функция библиотеки abs перегружен для разных типов аргументов (и возвращаемых). заголовок <stdlib.h> (или же <cstdlib>) обеспечивает перегрузки для целочисленных аргументов. заголовок <math.h> (или же <cmath>) обеспечивает перегрузки для аргументов с плавающей точкой.

Вопрос в этом случае заключается в том, какой заголовочный файл OP используется в программе. Если <math.h> был включен, то abs должен был позвонить double abs(double) и сгенерировал правильный результат (за исключением сломанного компилятора). Если <stdlib.h> был включен (и нет <math.h>), то вызов должен был привести к сбою разрешения перегрузки из-за доступности обоих abs(int) а также abs(long),

Это относится в равной степени к обоим abs а также std::abs, Какой из них использовать, зависит только от того, какие заголовочные файлы вы включаете: <stdlib.h><math.h> или же <cstdlib><cmath> соответственно. Обратите внимание, что с помощью std::abs вместо abs никак не влияет на эту проблему: набор перегруженных функций одинаков в обоих случаях.

Если в случае ОП int версия abs был вызван, это было бы причудой реализации. Там на самом деле DR, который занимается этой проблемой

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2380

3