12

それで、私はコンピューティングコンテストに参加していて、奇妙なバグに気づきました. pow(26,2) は常に 675 を返し、時には 674 を返しますか? 正解は 676 ですが、これらのエラーは pow(26,3) や pow(26,4) などでも発生します。興味深いことに、この種のエラーはこれまでに発生したことがありません。私が持っていたコンピューターは、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
4

1 に答える 1

12

この関数powは 2 つの浮動小数点値を操作し、一方を他方に累乗できます。これは、最小値から最大値までの値を処理できる必要があるため、近似アルゴリズムによって行われます。

これは近似アルゴリズムであるため、値が少し間違っている場合があります。ほとんどの場合、これで問題ありません。ただし、正確な結果を得たい場合は、使用しないでください。

整数に使用しないことを強くお勧めします。そして、2 番目のオペランドがわかっている場合 (この場合は 2)、これをはるかに高速に実行し、正しい値を返すコードに置き換えるのは簡単です。例えば:

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

実際の質問に答えるには: 一部のコンパイラはpow、1 つまたは両方の引数がわかっている場合、 への呼び出しを他のコードに置き換えたり、すべて一緒に削除したりできます。これにより、異なる結果が得られる理由が説明されます。

于 2012-12-08T08:20:33.433 に答える