これは100を出力します:
int j=2;
int i= pow(10,2);
printf("%d\n", i);
そして、これは99を出力します:
int j=2;
int i= pow(10,j);
printf("%d\n", i);
なんで?
これは100を出力します:
int j=2;
int i= pow(10,2);
printf("%d\n", i);
そして、これは99を出力します:
int j=2;
int i= pow(10,j);
printf("%d\n", i);
なんで?
pow
何が起こっているかというと、標準ライブラリの実装の品質が非常に低く、正確な結果が型 ( ) で表現できる場合でも、不正確な結果を返すC 実装があるということですdouble
。への呼び出しはpow(10,2)
、 のすぐ下の値を生成するように見え100.0
ます。これを整数に丸めると、99 になります。引数が定数の場合にこれが表示されない理由は、コンパイラが自由に呼び出しを最適化して置き換えたためです。コンパイル時に定数 100 を使用します。
整数のべき乗を行うことが目的の場合は、pow
関数を使用しないでください。適切な整数べき乗関数を書くか、指数がわかっている場合は、乗算を直接書き出すだけです。
最初のケースでは、コンパイラーが10*10
実際に呼び出すことなく値を最適化したのでpow
はないかと思います (コンパイラーは実際にこれを行います)。2 番目のケースでは、浮動小数点の丸めエラーがあるようです。結果はほぼ100 ですが、完全ではなく、暗黙のキャストによってint
切り捨てられます。
pow
関数はdouble
ではなく で動作しますint
。
一般に (常にではありませんが)、double を整数に変換するときは、 を呼び出しますround()
。例えば:
int i = (int) round(pow(10,j));
C ライブラリにこれがない場合は、次をエミュレートできます。
#define round(x) floor((x)+0.5)
pow
double
結果が正確ではなく100
、わずかに小さい場合は、に変換するときに切り捨てられ、表示されint
ている結果が返さ99
れます。double
変数と%f
形式の結果がどのように見えるかを見るのは興味深いでしょう。
リテラルを使用するときに表示されない理由は、呼び出しが最適化されて定数に置き換えられる定数の折りたたみのためです。pow
アセンブリを生成するときに定数を使用するバージョンを確認できます への呼び出しpow
は行われず、最終結果を移動するだけです100
(ライブを参照してください):
movl $100, -4(%rbp)
一方、2 番目のバージョンが実際に呼び出すバージョンpow
(ライブで参照してください):
call pow