【问题标题】:GCC C++ pow accuracyGCC C++ pow 精度
【发布时间】:2012-12-08 05:49:21
【问题描述】:

所以我参加了一个计算竞赛,我发现了一个奇怪的错误。 pow(26,2) 总是返回 675,有时返回 674?即使正确答案是 676。这类错误也会发生在 pow(26,3)、pow(26,4) 等 经过比赛后的一些调试,我相信答案与 int 向下舍入的事实有关。有趣的是,我以前从未发生过这种错误。我的计算机在 Windows 8 上运行 mingw。GCC 版本相当新,我相信 2-3 个月大。但我发现,如果我将 o1/o2/o3 优化标志打开,这些错误会奇迹般地消失。 pow(26,2) 总是会得到 676 又名正确答案 谁能解释为什么?

#include <cmath> 
#include <iostream> 

using namespace std; 
int main() { 
    cout<<pow(26,2)<<endl; 
    cout<<int(pow(26,2))<<endl; 
}

双打的结果很奇怪。

double a=26; 
double b=2; 
cout<<int(pow(a,b))<<endl; #outputs 675 
cout<<int(pow(26.0,2.0))<<endl; # outputs 676 
cout<<int(pow(26*1.00,2*1.00))<<endl; # outputs 676

【问题讨论】:

标签: c++ gcc mingw pow cmath


【解决方案1】:

函数pow 对两个浮点值进行运算,并且可以将一个提升到另一个。这是通过近似算法完成的,因为它需要能够处理从最小到最大的值。

由于这是一个近似算法,它有时会得到一些错误的值。在大多数情况下,这是可以的。但是,如果您有兴趣获得准确的结果,请不要使用它。

我强烈建议不要将它用于整数。如果第二个操作数是已知的(在这种情况下为 2),用执行速度更快并返回正确值的代码替换它是微不足道的。例如:

template<typename T>
T square(T x)
{
  return x * x;
}

回答实际问题:当一个或两个参数已知时,一些编译器可以用其他代码替换对pow 的调用,或者将其全部消除。这就解释了为什么会得到不同的结果。

【讨论】:

  • 您推荐使用宏而不是函数的任何特殊原因?
  • 另外,我会将 is known 替换为 is a known small integer。如果知道它是大的还是小数的,它并没有多大用处。
  • @NPE,我选择了一个宏,因为它是类型中性的,而且很容易输入:)。当然,如果你知道类型,你可以定义一个函数,或者一组重载函数,甚至是一个模板函数。
  • 我会赞成这个答案,但我非常不喜欢为此使用宏的想法,尤其是在 C++ 中。
  • 模板怎么样。两全其美。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多