1

int型の2つの変数を持つプログラムがあります。

int num;
int other_num;

/* change the values of num and other_num with conditional increments */

printf ("result = %f\n", (float) num / other_num);

float r = (float) num / other_num;
printf ("result = %f\n", r);

最初の printf に書き込まれた値は、2 番目の printf によって書き込まれた値とは異なります (小数点以下 6 桁で印刷した場合、0.000001)。

除算前の値は次のとおりです。

num = 10201 
other_num = 2282

結果の数値を小数点以下 15 桁まで出力しました。これらの数値は、小数点以下 7 桁目で異なり、6 桁目の違いを説明しています。

小数点以下15桁の数字は次のとおりです。

4.470201577563540
4.470201492309570

浮動小数点の丸めの問題は認識していますが、代入と printf 引数で実行した場合、計算結果が同じになることを期待していました。

なぜこの期待は間違っているのでしょうか?

ありがとう。

4

2 に答える 2

8

おそらくFLT_EVAL_METHOD、システムの が 0 以外であることが原因です。

最初のケースでは、式の(float) num / other_num名義型floatは ですが、より高い精度で評価される可能性があります (x86 を使用している場合は、おそらくlong double)。double次に、に渡すために に変換されprintfます。

2 番目のケースでは、結果を type の変数に代入し、float余分な精度を強制的に削除します。に渡されると、がfloatに昇格されます。doubleprintf

もちろん、実際の数字がなければ、これはすべて当て推量です。より明確な回答が必要な場合は、問題の完全な詳細を提供してください。

于 2013-05-17T22:19:51.113 に答える
1

ポイントは、プログラム実行中の式の結果の実際の位置です。C の値は、特定のケースでこの種の最適化が可能であるとコンパイラが判断した場合、メモリ (キャッシュを含む) またはレジスタのみに存在する可能性があります。

最初の printf では、値が同じ C 命令で使用されるため、式の結果がレジスタに格納されます。そのため、コンパイラは (正しく)、揮発性の低い場所に値を格納するのは無意味であると判断します。その結果、値はアーキテクチャに応じて double または long double として格納されます。

2 番目のケースでは、コンパイラはそのような最適化を実行しませんでした。値は、レジスタではなくメモリであるスタック内の変数に格納されます。したがって、同じ値が 23 番目の有効ビットで切り捨てられます。

その他の例は、streflopとそのドキュメントで提供されています。

于 2013-05-17T22:45:19.633 に答える