Numpy 数组浮点精度不是确定的

Numpy array float precision is not deterministic

提问人:ma7555 提问时间:3/3/2022 最后编辑:ma7555 更新时间:3/3/2022 访问量:507

问:

所以在运行下面的snipet时

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 有什么解决方案吗?

python 数组 numpy 浮点 精度

评论

0赞 Vezen BU 3/3/2022
根据您的观察使用 np.array([np.floor((x + 1) / 0.04) for x in X]) 怎么样?

答:

3赞 flawr 3/3/2022 #1

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

在第一个示例中

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

将生成一个 64 位的原生 Python,所以这里没有多余的东西。float()

在第二个示例中,您创建了一个 numpy 32 位标量 (),它将或多或少地被视为其他标量: 因此,只要添加 (1),结果将是一个 64 位数字。shape==(), type==np.float32int

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

评论

0赞 Jérôme Richard 3/3/2022
有趣。但是如何解释是 float32 并且是 float64?((X + np.float32(1)) / 0.04).dtype((X[0] + np.float32(1)) / 0.04).dtype
0赞 flawr 3/3/2022
在第一个示例中,第二个示例中将是一个标量,因此这又是与我在答案中提到的类似的情况。请注意,这与这里不同,前者仍然会给你一个numpy对象,而后者将是一个原生python!Xnp.ndarrayX[0]np.float32X[0]X.item()float
0赞 flawr 3/3/2022
所以为了回答你的问题,在第一种情况下,我们有一个数组,数组的类型通过标量运算得以保留,在第二种情况下,我们有一个标量,其中是一个 64 位 (0.04),结果将是一个 64 位数字。float
0赞 ma7555 3/3/2022
哪个也产生 19.0 呢np.floor(np.multiply((X + 1), 1/0.04))
0赞 flawr 3/3/2022
@ma7555我建议将其划分为所有中间结果,检查类型,然后考虑您究竟在哪里发现与预期存在差异!