C++ cmath'的正确性;GCC中的s pow()

C++ cmath'的正确性;GCC中的s pow(),c++,math,gcc,g++,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 <<

代码[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;
}
我想知道为什么
s=390624
应该是
390625
。如果我编译代码时没有-O2标志,则
s=390625
。此外,对
ss
的转换似乎可以解决问题

发生什么事了


我的操作系统是Windows7 Ultimate x64。不确定GCC版本,它附带了代码::Blocks 10.05。

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

int s = pow(ff, matrixa.size());

pow
的结果实际上更像是
390624.99999
的结果,当您将其截断为
int
时,它实际上被压缩为390624。如果您希望那里有一个整数值(一个小数部分为.0的浮点),您可能应该对
pow
的结果进行四舍五入,尝试将结果分配给一个
double
并输出它(可能使用更大的
std::setprecision
)设置。您将看到,由于舍入错误,该值类似于
390624.99999999999
(或类似值)


强制转换为整数会截断小数部分,因此留给您的是
390624
。使用
std::round
获得所需的结果。

我认为接下来的是4.4.1 IIRC。
double-pow(double,int)
在C++11 BTWWWorks中被正确删除(gcc-4.5.1,linux)。它可能通过数值近似(可能是牛顿方法)计算幂。有可能随着优化的启动,它将运行更少的迭代(并且精度更低)。如果你不将输出转换为int,你会得到什么?@wug:不知道你在问什么。我没有强制转换任何输出。此错误不是由浮点运算引起的。pow(5,8)完全可以表示为双精度,因此一个好的数学库应该精确返回390625。即使是只保证可靠舍入(小于1 ULP)而不是正确舍入(不超过1/2 ULP,且关系舍入为偶数)的库也会在这里得到正确答案。因此,如果pow没有返回正确的答案,问题在于库质量,而不是浮点算法。@EricPostChil是的,但是如果浮点算法是绝对理想的(不是,这是我的答案),即使是实现
pow
的(差)算法也不会产生任何偏差。所以我们可以说它是由IEEE浮点算法引起的。但我完全同意你的看法,在这种特殊情况下,责任在于实现了
pow
。理想的算法,即每一次运算都会产生精确的数学结果,不会导致pow产生正确的结果。这是因为浮点运算只提供加法、减法、乘法、除法、平方根和一些实用运算。这些不足以计算pow(对于一般参数;显然,可以计算像pow(5,8)这样的特定情况),因为算术运算只能计算平方根扩展的有理函数。因此,pow和其他数学库函数必须是近似的,即使使用完美的算法也是如此。
int s = pow(ff, matrixa.size());