abs()为一些非常大的double值返回负值

时间:2014-10-04 06:21:35

标签: c++ absolute

我正在处理一些重要的双重值,并且所有数学函数都很好。似乎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);
}

结果

  • Coliru2147483647.000000
  • g ++ 4.8.3-cygwin:-2147483648.000000

在此MCVE中,将abs更改为std::abs会因重载解析失败而导致编译错误(无法在std::abs<int>std::abs<long>,{{之间进行选择1}})。

2 个答案:

答案 0 :(得分:5)

当您在C ++ abs(int)中需要fabs(double)或更高版本时,问题是您正在使用std::abs()。你说你试过了std::abs(),但如果你有,那就解决了你的问题。

这是C ++中一个不幸的常见陷阱。切勿在前面使用abs()而不使用std::。这很危险。

答案 1 :(得分:3)

abs在其他答案中提到的C ++中返回int的说法完全不正确。在C ++标准库函数abs中,为不同的参数(和返回)类型重载。标头<stdlib.h>(或<cstdlib>)为整数参数提供重载。标头<math.h>(或<cmath>)为浮点参数提供重载。

这种情况下的问题是OP在程序中使用的头文件。如果包含<math.h>,则abs应调用double abs(double)并生成正确的结果(禁止编译器损坏)。如果包含<stdlib.h>(并且没有<math.h>),则由于abs(int)abs(long)的可用性,调用应导致重载解析失败。

这同样适用于absstd::abs。您应该使用哪一个仅取决于您包含的标题文件:<stdlib.h> - <math.h><cstdlib> - <cmath>。请注意,使用std::abs代替abs根本不会对此问题产生任何影响:在这两种情况下,重载函数集都是相同的。

如果在OP的情况下调用了int abs版本,那么这将是实现的一个怪癖。实际上有一个DR来处理这个问题

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