15

最近、私はコードのブロックを書きます:

const int sections = 10;

for(int t= 0; t < 5; t++){
   int i = pow(sections, 5- t -1);  
   cout << i << endl;
}

そして結果は間違っています:

9999
1000
99
10
1

このコードだけを使用する場合:

for(int t = 0; t < 5; t++){
    cout << pow(sections,5-t-1) << endl; 
}

問題はもう発生しません。

10000
1000
100
10
1

誰か説明してくれませんか?どうもありがとうございます!

4

8 に答える 8

12

浮動小数点値の表現により、pow(10.0, 5)9999.9999999 などになる可能性があります。それを切り捨てられた整数に割り当てると。

編集:cout << pow(10.0, 5);出力が丸められているように見える場合、それを確認するサポートドキュメントは現在ありません。

EDIT 2: BoBTFish によるコメントとこの質問pow(10.0, 5)は、 whenがその中で直接使用されていることを確認していcoutます。

于 2012-03-14T14:48:56.550 に答える
2

小数指数で使用する場合、 pow(x,y) は一般に として評価されexp(log(x)*y)ます。このような式は、無限の精度で評価されれば数学的には正しくなりますが、実際には丸め誤差が発生する可能性があります。他の人が指摘しているように、整数にキャストすると 9999.999999999 の値は 9999 になります。一部の言語とライブラリは、浮動小数点指数で指数演算子を使用するときに常にこのような定式化を使用します。他の人は、指数が整数である場合を識別し、適切な場合は反復乗算を使用しようとします。pow関数のドキュメントを調べると、xが負でy小数部がない場合に機能するはずです (xが負で`y偶数の場合、結果はpow(-x,y); の場合yが奇数の場合、結果は になります-pow(-x,y)y小数部分がない場合、負の値を処理するという問題を経験するライブラリが反復乗算を使用する必要があるのは論理的に思えますがx、そうしなければならないことを指示する仕様は知りません。

いずれにせよ、整数を累乗しようとしている場合は、計算に整数演算を使用するのがほぼ確実に最善です。累乗する整数が定数であるか、常に小さい場合は、単純にルックアップ テーブルを使用します。 (0 から 15 までの数値を 64 ビット整数に収まる累乗で累乗するには、4,096 項目のテーブルしか必要としません)。

于 2012-03-14T15:23:11.293 に答える
2

ここから

pow()関数を見ると、パラメーターと戻り値がすべて型double pow (double base, double exponent);であることがわかります。doubleただし、変数numiおよびresはすべてint上記のコードの型であり、にまたはに変換intすると、精度が失われる可能性があります。たとえば (厳密ではないかもしれませんが)、浮動小数点ユニット (FPU) は calculateを計算し、次にC++ の型によって変換します。doubledoubleintpow(10, 4)=9999.99999999int(9999.9999999)=9999

それを解決する方法は?

ソリューション1

コードを変更します。

    const int num = 10;

    for(int i = 0; i < 5; ++i){
       double res = pow(num, i);
       cout << res << endl;
    }

ソリューション2

型の計算精度が高い浮動小数点ユニット (FPU) に置き換えdoubleます。たとえば、Windows CPU では SSE を使用します。Code::Block 13.12 では、目標を達成するために次の手順を実行できます: 設定 -> コンパイラ設定 -> GNU GCC コンパイル -> その他のオプション、追加

-mfpmath=sse -msse3

写真は次のとおりです。

<code>-mfpmath=sse -msse3</code> を追加
(ソース: qiniudn.com )

于 2015-04-24T09:26:27.207 に答える
1

最初の例のコードが実行している正確なコードである場合は、バグのあるライブラリがあります。あなたが拾っているのか、ダブルをとるstd::powCのpowどちらを選んでいるかに関係なく、ダブルバージョンが選択されたとしても、10は正確に。として表すことができdoubleます。そのため、べき乗は正確にとして表すことができdoubleます。丸めや切り捨てなどは発生しません。

-ffast-mathg ++ 4.5では、とを使用しても(奇妙な)動作を再現できませんでし-O3た。

今私が起こっているのは、リテラル10が直接割り当てられているのでsectionsなく、その値がのようなものになるよう9.9999999999999に内部で読み取られたり計算されたりしていることです。これは、4乗すると。のような数値を生成し9999.9999999ます。次に、これは表示される整数9999に切り捨てられます。

ニーズに応じて、intに割り当てる前に、ソース番号または最終番号のいずれかを丸めることができます。例えば:int i = pow(sections, 5- t -1) + 0.5; // Add 0.5 and truncate to round to nearest.

于 2012-03-14T16:30:45.330 に答える
1

pow関数がdoubleを返すので、これを行うとどうなりますか

int i = pow(sections, 5- t -1);  

の 10 進数の .99999 カットで、9999 が得られます。

直接印刷したり、10000と比較したりしても、ある意味で使い古されているので問題ありません。

于 2012-03-14T14:52:19.340 に答える
0

結果をintに代入しています。それはそれを強制し、数を切り捨てます。

これはうまくいくはずです:

for(int t= 0; t < 5; t++){
   double i = pow(sections, 5- t -1);  
   cout << i << endl;
}
于 2012-03-14T14:52:07.267 に答える
0

powグローバル名前空間には壊れた関数がいくつかあるはずです。次にstd::pow、ADLのために、2番目の例で代わりに「自動的に」使用されます。

最初の例でtは、実際には浮動小数点数であり、丸めエラーが発生しています。

于 2012-03-14T14:47:20.697 に答える