向下舍入浮动

Rounding down float

首先让我给出 32 位浮点和十进制表示的十六进制和二进制。

0x5060000f = 01010000011000000000000000001111 = 15032400896
0x43800005 = 01000011100000000000000000000101 = 256.000152587890625

我的老师说添加 1 次 0x5060000f 和 24 次 0x43800005 浮点数在最后 3 位有舍入错误。

她是什么意思?

15032400896 + 24 * 256.000152587890625 =
15032407040.003662109375 =
01010000011000000000000000010101 =
0x50600015

首先,让我们看一下编码数字的部分,我将标记为a(15032400896)和b(256.000152587890625):

a: 0 10100000 11000000000000000001111
b: 0 10000111 00000000000000000000101

两个符号位都是0,表示数字是正数。 a 的指数字段是 10100000,即 160。编码后的指数偏移 127,因此实际指数为 160−127 = 33。(我假设使用 IEEE 754 基本 32 位二进制格式。 ) b的指数字段是10000111,也就是135,所以它的实际指数是8。

这些在floating-point的正常范围内(因为编码的指数不为零,当指数为零时,数字是次正规的。)在正常范围内,有一个隐含的“1。 ”前缀为有效数字。 (有效数是数字的小数部分。有时它被称为“尾数”,但这是纸质对数表时代的遗留术语。“有效数”是首选术语。)

第一个数字的有效数字域是 11000000000000000001111,所以实际有效数字是 1.11000000000000000001111(作为二进制数字)。第二个数的有效位域是00000000000000000000101,所以它的实际有效位是1.00000000000000000000101.

现在我们已经完全解码了数字,可以看到它们的数学值是:

a = 1.11000000000000000001111 • 233
b = 1.00000000000000000000101 • 28

问题是计算a24*b之和时会发生什么,所以首先我们需要找到24*b。由于 24 是一个简单的数字,我将跳过显示它的完整浮点表示,并简单地将 b 乘以 24。我们可以简单地通过将其有效数乘以 24 来实现,得到:

24*b = 11000.0000000000000000111 1 • 28

我用粗体标记了前 24 位,并在它们和其余位之间放了一个 space。这是因为 floating-point 格式的有效位只有 24 位。所以计算机必须舍入精确的数学结果以适合 24 位。我们可以向下舍入到 11000.0000000000000000111,或者向上舍入到 11000.0000000000000001000。由于剩余的位在它们之间是等距的,所以我们打成平手。 floating-point 中最常用的舍入规则是舍入到最接近的表示值,如果出现平局,则舍入到偶数。所以我们四舍五入,结果是:

24*b → 11000.0000000000000001000 • 28

接下来,我们要对表示进行规范化,以便尾数以“1”开头。而不是“11000”。为此,我们调整指数:

24*b → 1.10000000000000000001000 • 212

我将这个结果称为c。现在我们要添加ac,分别是:

a = 1.11000000000000000001111 • 233
c = 1.10000000000000000001000 • 212

当处理器将数字相加时,它有效地移动有效数字以对齐表示相同大小的位。对齐这些数字会产生:

1.11000000000000000001111000000000000000000000 • 233
0.00000000000000000000110000000000000000001000 • 233

然后我们可以将数字相加,得到:

1.11000000000000000010101000000000000000001000 • 233

使用粗体和一个space标记前24位显示:

1.11000000000000000010101 000000000000000001000 • 233

这一次,剩下的位都在中点以下,所以我们向下舍入,结果是:

1.11000000000000000010101 • 233

这显示了在 32 位 floating-point 中计算 a + 24*b 的最终结果。发生了舍入,但我不明白如何将其描述为“最后 3 位舍入错误”。如果结果是用精确的数学计算出来的,它将是:

1.110000000000000000101010000000000000000001111000 • 233

所以我们可以看到计算结果的最后一位是正确的,并且发生的舍入误差在数值上要小得多。