圆形连接甚至浮点减法

Jef*_*ffB 2 floating-point

舍入不像我期望的浮点减法那样工作.

IEEE754-2008,4.3.1说"roundTiesToEven ......如果包含无法代表的无限精确结果的两个最近的浮点数同样接近,那么具有最低有效数字的那个将被传递"

英特尔文档称这是默认模式并更明确地定义它:

https://software.intel.com/en-us/node/503710

我将首先介绍浮点加法 - 这正如我所期望的那样 - 来验证我的假设.然后,我会稍微修改我的测试用例,以显示我的理解中断的地方.

我们取两个单浮点数,这里用'binary32'格式表示:

S Exponent       Significand
0 10000010 00000000000000000000001  (0x41000001)
    130

0 01111111 00000000000000000000100  (0x3F800004)
    127
Run Code Online (Sandbox Code Playgroud)

要添加它们,我将数字的有效位数用较小的指数(第二个操作数)移动到右边3个位置(我还在这里添加了隐含的前导1):

   1.00000000000000000000001
+  0.00100000000000000000000  100
 ----------------------------
   1.00100000000000000000001
Run Code Online (Sandbox Code Playgroud)

因为移出的值在两者之间的中间位置(100),所以它应该舍入为偶数值的总和:

1.00100000000000000000010
Run Code Online (Sandbox Code Playgroud)

在二进制文件中,完整值为:

0 10000010 00100000000000000000010 (0x41100002)
Run Code Online (Sandbox Code Playgroud)

我可以验证这个:

#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);
}
Run Code Online (Sandbox Code Playgroud)

打印:

./a.out
41100002
Run Code Online (Sandbox Code Playgroud)

如果我在第一个操作数中添加一个:

    a.ival = 0x41000002;
Run Code Online (Sandbox Code Playgroud)

我得到了同样的东西.它已经向下舍入到均匀的结果:

./a.out
41100002
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是,如果我使用原始值并通过将符号位设置为1将第二个参数修改为负值:

a.ival = 0x41000001;
b.ival = 0xBF800004;
Run Code Online (Sandbox Code Playgroud)

我明白了:

./a.out
40E00001
Run Code Online (Sandbox Code Playgroud)

这是:

0 10000001 11000000000000000000001
    129
Run Code Online (Sandbox Code Playgroud)

在第二个参数对齐后,结果应该仍然在两个值之间.在这种情况下,为什么它没有达到均值?

Pat*_*han 6

要理解最终结果,重要的是要记住舍入是IEEE 754算法的最后一步.它通过标准化完成,然后舍入.

查看两个计算的高有效结束,两个操作数在显式位中都为零.隐含的一位b右移三个位置以匹配指数:

1.000
0.001
Run Code Online (Sandbox Code Playgroud)

添加这些给出1.001,因此指数保持相同a,并且结果中有一个明确的一位.

减去它们得到0.111.归一化将此左移一位,以消除前导0,给出1.110.结果中存储了两个显式的一位.

现在看看低意义的结局.原始减法将在"中间"位置留下一位.由归一化引起的左移将其转换为最不重要的存储位,结果是精确的.