为什么sin(180)在使用python和numpy时不为零?

2024-04-19 12:02:09 发布

您现在位置:Python中文网/ 问答频道 /正文

有人知道下面为什么不等于0吗?

import numpy as np
np.sin(np.radians(180))

或:

np.sin(np.pi)

当我把它输入python时,它给出了1.22e-16。


Tags: importnumpyasnppisinradians
3条回答

一种解决方案是在计算sin和cos时切换到sympy,然后使用sp.N(…)函数切换回numpy:

>>> # Numpy not exactly zero
>>> import numpy as np
>>> value = np.cos(np.pi/2)
6.123233995736766e-17

# Sympy workaround
>>> import sympy as sp
>>> def scos(x): return sp.N(sp.cos(x))
>>> def ssin(x): return sp.N(sp.sin(x))

>>> value = scos(sp.pi/2)
0

在使用scos和ssin函数时,请记住使用sp.pi而不是sp.np。

数字π不能完全表示为浮点数。所以,np.radians(180)不给你π,它给你3.1415926535897931

sin(3.1415926535897931)实际上类似于1.22e-16

那么,你怎么处理?

你必须计算出,或者至少猜测出,适当的绝对和/或相对误差界限,然后你写下:

abs(y - x) < abs_bounds and abs(y-x) < rel_bounds * y

(这也意味着您必须组织计算,以便相对于y的相对误差大于相对于x。在您的例子中,因为y是常量0,所以只需向后做就可以了。)

Numpy提供了一个跨整个数组执行此操作的函数,^{}

np.allclose(x, y, rel_bounds, abs_bounds)

(这实际上检查了abs(y - x) < abs_ bounds + rel_bounds * y),但这几乎总是足够的,而且您可以轻松地重新组织代码(如果不是这样的话)

就你而言:

np.allclose(0, np.sin(np.radians(180)), rel_bounds, abs_bounds)

那么,你怎么知道正确的界限是什么?在这么一个答案里没有办法教你足够的错误分析。Propagation of uncertainty在维基百科给出了一个高层次的概述。如果您真的不知道,可以使用默认值,即1e-5相对值和1e-8绝对值。

面对同样的问题

import numpy as np

print(np.cos(math.radians(90)))

>> 6.123233995736766e-17

试过这个

print(np.around(np.cos(math.radians(90)), decimals=5))

>> 0

对我的案子有效。我把十进制数设为5,不会丢失太多信息。正如你能想到的,舍入五位数后的值。

相关问题 更多 >