質問
正確な IEEE 754 算術演算を実装する C99 コンパイラの場合、型の の値がf
存在divisor
するfloat
かf / divisor != (float)(f * (1.0 / divisor))
?
編集: 「正確な IEEE 754 演算を実装する」とは、FLT_EVAL_METHOD を 0 として正当に定義するコンパイラを意味します。
環境
IEEE 754 準拠の浮動小数点を提供する AC コンパイラは、逆数自体が として正確に表現できる場合にのみ、単精度除算を定数で置き換え、単精度乗算を逆数で置き換えることができfloat
ます。
実際には、これは 2 のべき乗でのみ発生します。f / 2.0f
したがって、プログラマーのアレックスは、 が のようにコンパイルされると確信しているかもしれませんが、アレックスが 10 で割る代わりにf * 0.5f
を掛けることが許容される場合0.10f
、アレックスは、プログラムに掛け算を書くか、 GCC の-ffast-math
.
この質問は、単精度除算を倍精度乗算に変換することに関するものです。常に正しく丸められた結果を生成しますか? それが安くなる可能性はあり-ffast-math
ますか?
反例を見つけることなく、1 から 2 までのすべての単精度値に対してとを比較(float)(f * 0.10)
しました。これにより、法線のすべての分割がカバーされ、法線の結果が生成されます。f / 10.0f
f
float
次に、以下のプログラムを使用して、テストをすべての除数に一般化しました。
#include <float.h>
#include <math.h>
#include <stdio.h>
int main(void){
for (float divisor = 1.0; divisor != 2.0; divisor = nextafterf(divisor, 2.0))
{
double factor = 1.0 / divisor; // double-precision inverse
for (float f = 1.0; f != 2.0; f = nextafterf(f, 2.0))
{
float cr = f / divisor;
float opt = f * factor; // double-precision multiplication
if (cr != opt)
printf("For divisor=%a, f=%a, f/divisor=%a but (float)(f*factor)=%a\n",
divisor, f, cr, opt);
}
}
}
検索空間は、これを興味深いものにするのに十分な大きさです (2 46 )。プログラムは現在実行中です。終了する前に、おそらく理由または理由を説明して、何かを印刷するかどうかを誰かに教えてもらえますか?