Numpy 数组浮点精度不确定

Numpy array float precision is not deterministic

所以当运行下面的片段

import numpy as np

X = np.array([-0.20000008], dtype=np.float32)
np.floor((X + 1) / 0.04)
array([20.], dtype=float32)

输出显然是错误的,因为结果应该低于 20,应该降到 19

我知道这是精度错误,但是 运行 下面的所有样本都产生了正确的结果,尽管它们应该具有相似的精度

X = np.array([-0.20000008], dtype=np.float32).item()
np.floor((X + 1) / 0.04) # 19.0
X = np.float32(-0.20000008)
np.floor((X + 1) / 0.04) # 19.0
X = np.array([-0.20000008], dtype=np.float32)
np.floor(X / 0.04 + 1 / 0.04) # array([19.], dtype=float32)
np.floor(np.multiply((X + 1), 1/0.04)) # array([19.], dtype=float32)

如果我将其转换为 float64,它也可以工作,但对于我的应用程序来说,转换成本非常高。坚持使用 float32 时有什么解决方案吗?

让我们先尝试理解底部三个示例中的前两个:

在第一个例子中

np.array([-0.20000008], dtype=np.float32).item()

将生成原生的 python float(),它是 64 位的,所以这里没有惊喜。

在第二个示例中,您创建了一个 numpy 32 位 标量 (shape==(), type==np.float32),它或多或少会像其他标量一样被对待:所以只要您添加一个 int (1),结果将是一个 64 位数字。

现在有趣的情况实际上是您的初始代码段和第三个示例:在这两种情况下,您现在都有一个 array (shape==(1,), type=np.ndarray)。在使用数组和标量进行操作的情况下,数组的类型将被保留。所以现在我们实际上遇到的问题是 分配 定律不适用于浮点数。您在这里进行的计算依赖于浮点数的最低有效位。