numpy 为什么使用np.linalg.norm会引入看不见的数值不等式,而写出来却不会?

fnx2tebb  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(113)

假设我有两个变量:

import numpy as np
a = np.array([[ 0,  1, 10,  2,  5]])

b = np.array([[ 0,  1, 18, 15,  5],
              [13,  9, 23,  3, 22],
              [ 2, 10, 17,  4,  8]])

字符串

方法一

m1 = -np.linalg.norm(a[:, np.newaxis, :] - b[np.newaxis, :, :], axis=-1) ** 2 / 2

方法二

m2 = -np.sum(np.square(a[:, np.newaxis, :] - b[np.newaxis, :, :]), axis=-1) / 2


这两个输出看起来很相似(至少根据print()):

array([[-116.5, -346. ,  -73.5]])


>>> np.array_equal(m1, m2)
False


有趣的是,定义一个文字来检查相等性会导致:

>>> sanity_check = np.array([[-116.5, -346. ,  -73.5]])
>>> np.array_equal(sanity_check, m1)
False
>>> np.array_equal(sanity_check, m2)
True


为什么使用np.linalg.norm的方法是奇数?如果m1不相等,为什么它的print()看起来相等?

wkyowqbh

wkyowqbh1#

实际值中存在少量的数值误差:

>>> m1.tolist()
[[-116.49999999999999, -346.0, -73.5]]

>>> m2.tolist()
[[-116.5, -346.0, -73.5]]

字符串
这是因为:

>>> np.sqrt(8**2 + 13**2)**2
232.99999999999997

>>> 8**2 + 13**2
233


NumPy的printoptions控制打印多少位数字。默认情况下,它们是:

>>> np.get_printoptions()
{'edgeitems': 3, 'threshold': 1000, 'floatmode': 'maxprec', 'precision': 3, 'suppress': False, 'linewidth': 75, 'nanstr': 'nan', 'infstr': 'inf', 'sign': '-', 'formatter': None, 'legacy': False}

omtl5h9j

omtl5h9j2#

基本上,浮点运算只提供近似结果。非常好的近似值,但根据计算的执行方式而有所不同。
对于这类指向What Every Programmer Should Know About Floating-Point Arithmetic的问题,应该有一个规范的答案。

相关问题