【问题标题】:Why does a fixed-point scaling factor tend to be a power of two?为什么定点比例因子往往是 2 的幂?
【发布时间】:2021-08-19 06:21:27
【问题描述】:

假设我们有两个浮点值:1.234.56。 要在不支持浮点的机器中表示和添加这些,我们将不得不回退到定点表示。

所以我们选择数字100作为比例因子,只是为了去掉小数点:

1 - 按比例因子将它们倍增 => 123456

2 - 添加他们123 + 456 = 579

3- 除以相同的比例因子 => 5.79

等于浮点数加1.23 + 4.56 = 5.79

现在,为什么我一直在阅读有关比例因子往往是 2 次方的在线文章?

https://en.wikipedia.org/wiki/Scale_factor_(computer_science)

https://www.allaboutcircuits.com/technical-articles/fixed-point-representation-the-q-format-and-addition-examples/

如果我选择 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 + 2/10 + 3/100,而是 1 + 1/2 + 1/8。
  • 使用二进制与十进制不会“破坏精度”。您给出的示例中的准确性丢失有两个原因:第一,在二进制样本中,您使用的比例因子(32)比十进制样本(100)小得多。二,您的样本中的数字完全可以用十进制表示。这种十进制数字仅在人类已经将数字四舍五入或以这种方式创建它们的情况下才常见。它们在自然界中并不经常出现——⅓ 不能精确地用十进制表示,物体的质量和速度永远不会或几乎永远不会是克或 m/s 的十进制数。
  • 对数学和物理中出现的数字的一般分布使用十进制定点会产生舍入误差,就像二进制定点一样。
  • @EricPostpischil 谢谢,所以本质上,二进制选择 2 的幂的原因是因为使用位移计算变得更快?
  • @Dan:是的。我会发布一个答案,但现在必须出去,并想考虑是否还有其他原因。

标签: floating-point ieee-754 fixed-point


【解决方案1】:

等于浮点数加 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) 将继续占主导地位,而不是切换到十进制浮点。

【讨论】:

  • 谢谢,你如何选择比例因子?它本质上是“越多越好”吗?还假设我们有 N 位用于显示一个固定点。是否可以使用定点显示该范围内的每个小数?或者无论我们拥有多少位数,都有无法显示的小数?我已经知道,例如,十分之一 (0.1) 和百分之一 (0.01) 只能近似表示。
  • @Dan 使用多少位?:需要知道要编码的最大定点值,以及需要的精度。例如(log2(max_value/precsision_needed) + 1 表示符号)。如果没有足够的可用位,则必须提供一些东西。
  • 我明白了,在问题的第二部分,我们可以使用定点显示给定范围内的每个小数吗?还是总会有无法表示的数字?
  • @Dan 如果定点整数类型实现:是,如果用二进制FP类型:否。
  • @Dan 0.01 按 100 缩放并保存为定点整数是 100。按 /100 缩小,0.01 可以精确地得到 - 作为文本。 0.01(可能是文本)按 100 缩放并保存为二进制 FP 为 100.0。按比例缩小 (double/100),double 商约为 0.0100000000000000002081...。当然,打印时会四舍五入为小数点后0.01 - 但商不完全是 0.01。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
相关资源
最近更新 更多