2

これはかなり初歩的な質問だと思いますが、これら 2 つのコードで異なる結果が得られる理由がわかりません。Pentium は変数 Divider を中間値 ( 256.0 / (double)k ) とは異なる方法で処理しますか?

int j=64, k=20;  
double x, y, Divider;

Divider = 256.0 / (double)k;
x = (double)j / Divider - 5.0;
y = (double)j / ( 256.0 / (double)k ) - 5.0;

結果: x = -2.77555756156289E-16 y = 0.0

参考までに、私は Embarcadero の XE3 C++ Builder を使用していますが、これは Builder 6 と同じ結果をもたらします。両方でデフォルトのコンパイラ設定を使用しています。

4

2 に答える 2

2

問題は、SSE 命令を使用しない場合、コンパイラが、387すべての計算を 80 ビット値で行うネイティブ浮動小数点ユニットを使用して中間計算を行うことを選択する可能性があることです。

の計算ではx、中間値を に格納することで強制的に 64 ビットに切り捨てますDivisor。次に、次の除算では、既に丸められた除数が使用されます。除算は十分な精度で行われるため、結果は 5.0 とはわずかに異なります。

の計算でyは、除算は 80 ビット精度で行われるため、結果は 5.0 に近くなります (64 ビットに切り捨てると 0 になるのに十分近い)。

0また、 SSE (64 ビット レジスタしかない) を使用する場合、またはコンパイラにすべての計算を 64 ビット精度で実行させる場合、2 つの値が得られます。

于 2013-09-05T15:27:08.083 に答える
0

おそらくそれはオプティマイザーです。2つ目では

y = (double)j / ( 256.0 / (double)k )

数学的には

y = (double)j * (double)k / 256.0

これは 1 つの除算のみを行い (偶然にもきれいに除算されます)、丸め誤差が少なくなります。

というのは、xそれは 2 つの分割を行うことを余儀なくされているからです。

于 2013-09-05T14:50:54.043 に答える