为什么将整数转换为 float16 是危险的?

Why is it dangerous to convert integers to float16?

我最近 运行 遇到了一个令人惊讶和烦人的错误,我将一个整数转换为 float16 并且值发生了变化:

>>> import numpy as np
>>> np.array([2049]).astype(np.float16)
array([2048.], dtype=float16)
>>> np.array([2049]).astype(np.float16).astype(np.int32)
array([2048.], dtype=int32)

这可能不是错误,因为 PyTorch 也会发生这种情况。我猜这与半浮点数表示有关,但我无法弄清楚为什么 2049 是第一个被错误转换的整数。

这个问题与Python没有特别相关(我猜)

IEEE 754 规范允许 float16 11 位用于有效数(小数),5 位用于指数。我想象试图表示 2049 你达到了有效数字的位限制,2 ** 11 == 2048

但是我不确定为什么 2049 会变成 2048。

来源:wikipedia:IEEE_754

你是对的,它通常与 floating-point 数字的定义方式有关(如其他人所说,在 IEEE 754 中)。让我们看看:

浮点数由符号 s(此处为 1 位)、尾数 m(此处为 10 位)和指数 e(此处为 5 位,表示 −14 ≤ e ≤ 15)表示。然后通过

计算浮点数x
x=s*[1].m*b**e,

其中基 b 为 2,[1] 为固定 (for-free) 位。

最多2**11我们的整数可以用尾数精确表示,其中

  • 2** 11-1 表示为 m = bin(2**10-1) 和 e = bin(10)
  • 2**11 表示为 m = bin(0) 和 e = bin(11)

然后事情变得有趣了:

  • 2**11+1不能用我们的尾数准确表示,四舍五入。
  • 2**11+2 可以表示(由 m = bin(0) 和 e = bin(11))

等等...

观看此视频了解详细示例https://www.youtube.com/watch?v=L8OYx1I8qNg