Python Numpy - 将非常小的数字视为零

6
我想用Numpy计算一个奇异矩阵(行列式为0),当我打印行列式时,它显示一个非常小的数值(接近于零的-7.09974814699e-30),而不是零本身...
当我尝试使用%s、%d或%f打印行列式时,有时是零,有时是-0,有时是-7.09974814699e-30。
以下是代码:
import numpy as np

array = np.arange(16)
array = array.reshape(4, -1)
determinant = np.linalg.det(array)

print("Determinant is %s" % determinant)
print("Determinant is %d" % determinant)
print("Determinant is %f" % determinant)

Determinant is -7.09974814699e-30
Determinant is 0
Determinant is -0.000000

如何让Numpy将诸如-7.09974814699e-30这样的非常小的数字视为零,并显示为零。我之前也问过这个问题,如果你看一下矩阵,你会发现它充满了非常小的数字,而不是零,而实际上它应该是一个对角矩阵,对角线上有数字,其他地方都是零。

你可以设置一个阈值:如果行列式小于0.00001,则将行列式设为0.0。 - Nikaido
我希望有一种全局的方法可以使Numpy将非常小的值显示为零,并避免在代码中使用许多if-else检查... - Cypher
你可能想考虑使用numpy.isclose,它可以检查值是否在给定的公差范围内。 - Kenji Noguchi
4个回答

4
>>> if np.abs(determinant) < 0.000001:
...     determinant=0
...
>>> print determinant
0

在数组的情况下,您可以使用单个操作来完成此操作(请参阅我对您其他问题的答案:https://stackoverflow.com/a/36395905/5088142)。
将小于eps的数组元素设置为零:
array[np.abs(array) < eps] = 0

3
你可以使用np.round来截断不太重要的小数位。但是最好保持浮点运算的精度。你只需要控制最终输出的格式,可以使用str.format函数。
In [7]: a=rand(12,12)
In [8]: deta=det(a)
#0.0063854296972496311

In [10]: detar=det(a.round(3))
# 0.0063817871557592153

In [12]: '{:.5f}'.format(deta)
Out[12]: '0.00639'

In [13]: '{:.5f}'.format(detar)
Out[13]: '0.00638'

最后一行显示了由于之前的优化而导致的错误结果。

2

使用 numpy.set_printoptions 并启用 suppress 选项:

>>> import numpy as np
>>> np.set_printoptions(precision=3, suppress=True)
>>> array = np.arange(16)
>>> array = array.reshape(4, -1)
>>> determinant = np.linalg.det(array)
>>> print("Determinant is:", determinant)
Determinant is: 0.0

这个可以工作,但它也修改了较大数字的打印方式,并抑制了对大于1e3的科学计数法的使用 - 文档提供了一些进一步的信息。 - Taylor Alex Raine

1

我正在使用Python 2.7.11 |Anaconda custom (x86_64)|(默认版本为Dec 6 2015, 18:57:58)IPython 4.0.3 - 一个增强交互式Python。以下是我的结果:

In [6]: print("Determinant is %s" % determinant)
Determinant is 0.0

In [7]: print("Determinant is %d" % determinant)
Determinant is 0

In [8]: print("Determinant is %f" % determinant)
Determinant is 0.000000

我认为如果您更新numpy,它可能适合您,否则您可以使用以下方法。
In [9]: sam = 0.000000121

In [10]: sam
Out[10]: 1.21e-07

In [11]: print sam if sam > 0.00001 else 1
1

这并不完全回答你的问题"如何让Numpy将非常小的数字,如-7.09974814699e-30视为零,并向我显示零。",我认为你需要对此进行一些处理。
通常,在浮点数/指数方面,超出一定范围的计算会带来轻微的误差,例如你的e的-30次幂的情况。因此,如果你使用高级浮点数或指数,最好预期一些误差。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接