浮点加法的问题。忽略一些小值

Problems with floating-point additions. Ignoring some small values

我正在查找一本关于 CUDA 的书。

在讲解CUDA浮点数的那一章,我发现了一些奇怪的东西。

书上说(1.00 * 1) + (1.00 * 1) + (1.00 * 0.01) + (1.00 * 0.01) = 10。所有数字都是二进制数。 0.01指的是小数0.25.

因此,在十进制中连续添加 1 + 1 + 0.25 + 0.25 结果为 2。

书上说了为什么会这样;完成 1+1 后,它将忽略 +0.25,因为它与另一个操作数(1+1、2 的结果)相比太小了。

在这之后,他们说做 0.25 + 0.25 + 1 + 1 会产生 2.5,因为 0.5 被认为足以加上 1。

这是什么意思?处理器如何判断 0.25 与 2 相比太小了?这有明确的标准吗?

所有这些工作(或不工作)的机制是,如果您将数字加在一起,则较小的数字(绝对值)的一些精度会丢失。这来自执行操作的有限精度。

求和的数字之间的差距越小,损失越小。

在你的例子中,当你做 1+1 时,你得到 2。然后 0.25 比 2 小 10 倍。你的书表明这是一个很大的因素0.25 非常小,就像加 0(这是 0.25 在 2 设置的数量级上的近似值)。同样的事情发生在第二个 0.25 上:它什么都不加。

当您从 0.25+0.25 开始时,您将两个大小相同的数字相加,因此您得到完美的 0.5。然后当你加 1 时,你是在将两个数 相加,比率仅为 2:这比前一种情况的因数 10 小得多,你的书上说可以做到,所以你得到的总数是 1.5。然后是剩余的第 1 项:您将 1.5 和 1 相加;两者之间的因数 只是 1.5,所以,同样可以这样做,你得到 2.5.

该示例隐式声明了二进制浮点格式,它具有任意精度指数,但尾数中只有 2 位。所有数字的格式都是 1.xx * 2^n.

执行浮点加法时,必须对参数进行反规范化或缩放以使其具有相同的指数。

   0.25 =   1e-2 = 0.5e-1 = 0.25e0 = 0.125e1
   2.00 =   1e1

但是同一个基数0.125 = 0.001,不能用小数点后2位尾数表示。

就算加上字长也没关系:

  0.25 = 0.001000000000000000 (e=1)
  2.00 = 1.000000000000000000 (e=1)
  ---------------------------------
  2.25 = 1.001000000000000000 (e=1)
           ^^

结果将是小数点后的那两位,即(1.00e1) = 2。