3

以下では、result1 および result2 変数の値は、GCC 4.2.1 および GCC 3.2.0 で -g または -O を使用してコードをコンパイルするかどうかに応じて、異なる値を報告しています (さらに最近の GCC バージョンは試していません)。 :

double double_identity(double in_double)
{
    return in_double;
}

...

double result1 = ceil(log(32.0) / log(2.0));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result1==" << result1 << std::endl;

double result2 = ceil(double_identity(log(32.0) / log(2.0)));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result2==" << result2 << std::endl;

-g を使用してコンパイルした場合のみ、結果 1 および結果 2 == 5 になりますが、代わりに -OI でコンパイルすると、結果 1 == 6 および結果 2 == 5 が得られます。

これは、コンパイラによる最適化の仕方の違いか、IEEE 浮動小数点表現の内部的な違いのように思えますが、この違いが正確にどのように発生するのか興味があります。可能であれば、アセンブラを見ないようにしたいと思っています。

上記は C++ でコンパイルされていますが、printfs を使用して ANSI-C コードに変換された場合も同じことが当てはまると思います。

上記の不一致は 32 ビット Linux で発生しますが、64 ビット Linux では発生しません。

ありがとうございます

4

1 に答える 1

6

x86 では、最適化がオンの場合、部分式の結果は、より大きな式の一部として使用される前に、必ずしも 64 ビットのメモリ位置に格納されるとは限りません。

x86 の標準の浮動小数点レジスタは 80 ビットであるため、このような場合に追加の精度が利用できることを意味します。次に、その特に正確な値を別の値で割る (または掛ける) と、精度が向上したことによる効果が、肉眼で認識できるレベルまで拡大されます。

Intel の 64 ビット プロセッサは、浮動小数点演算に SSE レジスタを使用しますが、これらのレジスタには特別な精度はありません。

本当に気にする場合は、g++ フラグをいじってこれを修正できます

于 2010-07-24T05:26:39.423 に答える