62

この質問は、非常に興味深い現象を示しています。非正規化されたフロートは、コードを 1 桁以上遅くします。

動作は、受け入れられた回答でよく説明されています。ただし、現在153件の賛成票があり、満足のいく答えが見つからないコメントが1つあります。

この場合、コンパイラが +/- 0 をドロップしないのはなぜですか?!? – マイケル・ドーガン

補足: 0f は正確に表現可能である必要がある (さらに、バイナリ表現はすべてゼロでなければならない) という印象がありますが、c11 標準ではそのような主張を見つけることができません。これを証明する引用、またはこの主張を反証する議論は大歓迎です。とにかく、マイケルの質問がここでの主な質問です。


§5.2.4.2.2

実装では、ゼロおよび浮動小数点数ではない値 (無限大や NaN など) に符号を付けるか、符号なしのままにすることができます。

4

2 に答える 2

66

浮動小数点の正のゼロの追加は恒等演算ではないため、コンパイラはこれを排除できません。IEEE 754 規則により、+0 を加算した結果。-0に。-0 ではありません。; +0 です。

コンパイラは、+0 の減算を削除する場合があります。または-0の追加。それらはアイデンティティ操作であるためです。

たとえば、これをコンパイルすると:

double foo(double x) { return x + 0.; }

-O3Intel Mac でApple GNU C 4.2.1 を使用すると、結果のアセンブリ コードにaddsd LC0(%rip), %xmm0. これをコンパイルすると:

double foo(double x) { return x - 0.; }

add 命令はありません。アセンブリは入力を返すだけです。

したがって、元の質問のコードには、このステートメントの追加命令が含まれている可能性があります。

y[i] = y[i] + 0;

しかし、この声明の指示は含まれていませんでした:

y[i] = y[i] - 0;

ただし、最初のステートメントは の非正規値を使用した算術演算を含んでy[i]いたため、プログラムの速度を低下させるのに十分でした。

于 2013-05-10T10:30:59.550 に答える