GCC中cmath的pow()的正确性

Don*_*alo 4 c++ math gcc g++

代码 [GCC,用-O2标志编译]

int main()
{
    vector< vector<int> > matrixa(8);
    int ff = 5;
    int s = pow(ff, matrixa.size());
    int ss = pow(double(ff), int(matrixa.size()));
    vector< vector<int> > comb(s);
    cout << ff << "^" << matrixa.size() << " = " << s << endl;
    cout << ss << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

产量

5^8 = 390624
390625
Run Code Online (Sandbox Code Playgroud)

我想知道为什么s = 390624它应该是390625.如果我编译没有-O2标志的代码,那么s = 390625.此外,铸件ss似乎纠正了问题.

这是怎么回事?

我的操作系统是Windows 7旗舰版x64.不确定GCC版本,它附带Code :: Blocks 10.05.

Des*_*ume 6

因为浮点运算并不完美,而且当你这样做时

int s = pow(ff, matrixa.size());
Run Code Online (Sandbox Code Playgroud)

结果pow实际上是更像是什么390624.99999,当你截断它int有效时,它被平铺到390624.如果你期望一个整数值(一个浮点数.0小数部分),你可能应该舍入结果pow.

  • 此错误不是由浮点运算引起的.pow(5,8)完全可以表示为double,因此一个好的数学库应该返回390625.即使是一个只保证忠实舍入(小于1 ULP)而不是正确舍入的库(不超过1/2 ULP with在这里得到正确的答案.因此,如果pow没有返回正确的答案,问题是库质量,而不是浮点算术. (3认同)

Pla*_*aHH 5

尝试将结果分配给a double并输出(可能更大std::setprecision)设置.您将看到由于舍入错误,该值将类似于390624.99999999999(或类似).

转换为int会截断小数部分,从而使您无法使用390624.使用std::round以获得期望的结果.