簡単に書くと
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
pow
あなたは何を参照することになっていると思いますか?C++ 標準では、cmath をインクルードした後、グローバル スコープで pow 関数を使用できることさえ保証されていません。
すべてのオーバーロードが少なくともstd
名前空間にあることに注意してください。pow
整数指数を取るpow
関数と、浮動小数点指数を取る関数があります。C++ 実装がグローバル スコープで C pow 関数のみを宣言している可能性は十分にあります。この関数は浮動小数点指数を取ります。問題は、この関数にはいくつかの近似誤差と丸め誤差がある可能性が高いということです。たとえば、その機能を実装する 1 つの可能な方法は次のとおりです。
double pow(double base, double power)
{
return exp(log(base)*power);
}
pow(10.0,2.0) は、丸め誤差と近似誤差のために 99.99999999992543453265 のような結果になる可能性が十分にあります。浮動小数点から整数への変換によって小数点の前の数値が得られるという事実と組み合わせると、99+3=122 であるため、122 という結果が説明されます。
整数指数を取る pow のオーバーロードを使用したり、float から int への適切な丸めを行ったりしてみてください。整数指数を取るオーバーロードは、10 の 2 乗の正確な結果を与える可能性があります。
編集:
ご指摘のとおり、std::pow(double,int) オーバーロードを使用しようとすると、100 をわずかに下回る値が得られるようです。時間をかけて、ISO 標準と libstdc++ の実装を確認し、C++ から始まることを確認しました。 11 では、欠陥レポート 550を解決した結果、整数の指数を使用するオーバーロードが削除されました。C++0x/C++11 サポートを有効にすると、libstdc++ 実装のオーバーロードが実際に削除されます。これにより、改善が見られなかった理由を説明できます。
とにかく、特に整数への変換が含まれる場合、そのような関数の精度に頼るのはおそらく悪い考えです。浮動小数点値が整数 (100 など) であると予想し、それを int 型の値に変換する場合、ゼロに向かうわずかな誤差は明らかに大きな違いを生みます。したがって、私の提案は、すべての整数を取る独自の pow 関数を作成するか、独自のラウンド関数を使用して double->int 変換に関して特別な注意を払い、ゼロに向かうわずかなエラーが結果を変更しないようにすることです。