提问人:ma7555 提问时间:3/3/2022 最后编辑:ma7555 更新时间:3/3/2022 访问量:507
Numpy 数组浮点精度不是确定的
Numpy array float precision is not deterministic
问:
所以在运行下面的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 有什么解决方案吗?
答:
3赞
flawr
3/3/2022
#1
让我们先试着理解底部三个示例中的前两个:
在第一个示例中
np.array([-0.20000008], dtype=np.float32).item()
将生成一个 64 位的原生 Python,所以这里没有多余的东西。float()
在第二个示例中,您创建了一个 numpy 32 位标量 (),它将或多或少地被视为其他标量: 因此,只要添加 (1),结果将是一个 64 位数字。shape==(), type==np.float32
int
现在有趣的情况实际上是您的初始代码段和第三个示例:在这两种情况下,您现在都有一个数组 ()。在使用数组和标量进行操作的情况下,将保留数组的类型。所以现在我们实际上只是有一个问题,即分配律不适用于浮点数。在这里,您正在执行依赖于浮点数的最低有效位的计算。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!X
np.ndarray
X[0]
np.float32
X[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我建议将其划分为所有中间结果,检查类型,然后考虑您究竟在哪里发现与预期存在差异!
评论