9

これは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);

なんで?

4

3 に答える 3

13

pow何が起こっているかというと、標準ライブラリの実装の品質が非常に低く、正確な結果が型 ( ) で表現できる場合でも、不正確な結果を返すC 実装があるということですdouble。への呼び出しはpow(10,2)、 のすぐ下の値を生成するように見え100.0ます。これを整数に丸めると、99 になります。引数が定数の場合にこれが表示されない理由は、コンパイラが自由に呼び出しを最適化して置き換えたためです。コンパイル時に定数 100 を使用します。

整数のべき乗を行うことが目的の場合は、pow関数を使用しないでください。適切な整数べき乗関数を書くか、指数がわかっている場合は、乗算を直接書き出すだけです。

于 2013-10-01T23:08:05.110 に答える
2

最初のケースでは、コンパイラーが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)
于 2013-10-01T22:19:18.683 に答える
0

powdouble結果が正確ではなく100、わずかに小さい場合は、に変換するときに切り捨てられ、表示されintている結果が返さ99れます。double変数と%f形式の結果がどのように見えるかを見るのは興味深いでしょう。

リテラルを使用するときに表示されない理由は、呼び出しが最適化されて定数に置き換えられる定数の折りたたみのためです。powアセンブリを生成するときに定数を使用するバージョンを確認できます への呼び出しpowは行われず、最終結果を移動するだけです100ライブを参照してください):

movl    $100, -4(%rbp)

一方、2 番目のバージョンが実際に呼び出すバージョンpow(ライブで参照してください):

call    pow
于 2013-10-01T22:24:05.783 に答える