问题描述
假设我们有两个浮点值:1.23
和 4.56
。
要在没有浮点支持的机器中表示和添加这些,我们将不得不回退到定点表示。
所以我们选择100作为比例因子,只是为了去掉小数点:
1 - 通过比例因子将它们相乘 => 123
和 456
2 - 添加它们 123 + 456 = 579
3- 除以相同的比例因子 => 5.79
等于浮点加1.23 + 4.56 = 5.79
现在,为什么我继续阅读在线文章,其中缩放因子往往是 2 的幂?
https://en.wikipedia.org/wiki/Scale_factor_(computer_science)
如果我选择说 2^5 = 32
作为我的缩放因子,那么我们有:
-> 1.23 * 32 = 39.36 ~= 39
-> 4.56 * 32 = 145.92 ~= 145
-> 39 + 149 = 188
-> 188 / 32 = 5.87
5.87
的输出甚至不精确。那么为什么我们选择 2 的幂呢?
为什么我们不直接选择 10 的幂作为因数?
编辑
我也看到过这样的帖子: https://spin.atomicobject.com/2012/03/15/simple-fixed-point-math/
选择 2 的幂是因为计算机可以快速表示它们,即 2^16
可以通过位移来完成: 1 << 16
,但是 10 的幂不能计算得那么快。
是吗?我们基本上会因为一点延迟(如果有的话)而破坏精度?
解决方法
等于浮点数加1.23 + 4.56 = 5.79
不完全。
1.23、4.56、5.79 作为源代码是完全可以表示的。作为用 binary64 编码的浮点数,它们不是。就像 0.3333 不完全是三分之一一样,IEE-754 二进制使用附近的值 - 在 253 的 1 部分之内。因此,相加可能提供预期的总和,或者可能出现非常接近的其他总和。
为什么我一直在阅读在线文章,其中缩放因子往往是 2 的幂?
使用二进制浮点数,按 2 的幂进行缩放不会注入精度损失。该产品与其预先标定的值完全一样。
为什么我们不选择 10 的幂作为因数?
按 10 的幂进行缩放在纸面上效果很好(经典数学),但对于二进制浮点,乘积可能不精确,而是使用了四舍五入的值。因此,我们的缩放会注入一个小错误。
是吗?我们基本上会因为一点延迟(如果有的话)而破坏精度?
不,还有更多问题。由于存在如此多的问题并且速度很重要,因此浮点硬件制造商需要一个非常具体的 IEEE-754。即使在 40 年后,也会出现极端情况。在过去的 20 年里,IEEE-754 的十进制 版本也存在。整个规范的那部分正在缓慢地在硬件中实现,而不是 slooooow 软件十进制浮点实现。在市场推动更广泛的接受之前,二进制浮点与经典数学 (1.23 + 4.56) 之间的差异将继续占据主导地位,而不是转换为十进制浮点。