浮動小数点減算では丸めが期待できません。浮動小数点の減算でも丸めを行います
IEEE754-2008、4.3.1は「roundTiesToEvenを...でも最下位桁が配信されなければならないと表現できない無限に正確な結果をブラケット最も近い2つの浮動小数点数は、均等に近い1であれば、」言う
インテルのドキュメントは、これはデフォルトのモードであると言う、より明示的に定義します。私は最初の浮動小数点加算を歩くよ
https://software.intel.com/en-us/node/503710
- 私の仮定を検証するために - 私は期待通りに動作します。次に、私の理解が崩れている箇所を示すために、テストケースを少し修正します。
さんは「binary32」形式でここに表される2つの浮動小数点数を、見てみましょう:
S Exponent Significand
0 10000010 00000000000000000000001 (0x41000001)
130
0 01111111 00000000000000000000100 (0x3F800004)
127
は私が小さい指数(第2オペランド)との数の仮数をシフトし、それらを追加するには右へ3ヶ所(私もここに暗黙のリード1を追加しました):
1.00000000000000000000001
+ 0.00100000000000000000000 100
----------------------------
1.00100000000000000000001
シフトアウトした値は、2(100)間の途中にあるので、それも値に合計を丸める必要があります。
バイナリで1.00100000000000000000010
、完全な値は次のとおりです。
0 10000010 00100000000000000000010 (0x41100002)
私はこれを確認することができます:私は最初のオペランドに1を追加した場合
./a.out
41100002
:
#include <stdint.h>
#include <stdio.h>
union uval {
float fval;
int32_t ival;
};
int main()
{
union uval a, b, c;
a.ival = 0x41000001;
b.ival = 0x3F800004;
c.fval = a.fval + b.fval;
printf("%08x\n", c.ival);
}
版画:
a.ival = 0x41000002;
私は同じことを取得します。
./a.out
41100002
をこれまでのところ、とても良い:それも結果にダウンを四捨五入しています。私は元の値を使用して修正する場合は、2番目のパラメータは1に符号ビットを設定することにより、負に:私は
a.ival = 0x41000001;
b.ival = 0xBF800004;
を得る:
./a.out
40E00001
はどれ:
0 10000001 11000000000000000000001
129
結果は、2番目のパラメータがアライメントされた後も、2つの値の中間になっているはずです。この場合、なぜそれは同じ値に丸められなかったのでしょうか?
なぜ最終結果が正確に表現できるのではなく、その中間になると思いますか? –
私はそれを整列させるときに第2オペランドから数字 '100'をシフトしたので(ソースオペランドの指数は3だけ異なります)。 – JeffB
重要度の高い終わりで何が起きているのか、結果の指数が変わったのか考えましたか? –