Я работал с некоторыми большими двойными значениями, и все математические функции были в порядке. Кажется, что sqrt, pow и другие математические функции не имеют проблем с большими научными двойными значениями, но abs не может обработать эти числа.
например, это нормально:
double s = sqrt(3.9 * 1e32);
но это не так:
double s = sqrt(abs(3.9 * 1e32));
потому что abs возвращает отрицательное значение;
Я не понимаю, почему эта простая функция не может обрабатывать научные двойные операции, когда все эти сложные работают нормально. Я что-то упустил или это действительно так, и я не могу использовать функцию c ++ abs для таких значений?
#include <cstdlib>
#include <cstdio>
int main()
{
double d = 3.9e32;
double f = abs(d);
std::printf("%f\n", f);
}
2147483647.000000
-2147483648.000000
В этом MCVE меняется abs
в std::abs
вызывает ошибку компиляции из-за ошибки разрешения перегрузки (не может выбирать между std::abs<int>
, std::abs<long>
, std::abs<long long>
).
Проблема в том, что вы используете abs(int)
когда ты нуждаешься fabs(double)
или лучше в C ++, std::abs()
, Вы сказали, что пытались std::abs()
, но если бы у вас было, это бы решило вашу проблему.
Это печальная и распространенная ловушка в C ++. Никогда не используйте abs()
без std::
на передней. Это опасно.
Утверждение, что 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