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

时间:2013-09-05 21:45:04

标签: python numpy sin

有谁知道为什么以下不等于0?

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

或:

np.sin(np.pi)

当我进入python时,它给了我1.22e-16。

6 个答案:

答案 0 :(得分:15)

数字π不能完全表示为浮点数。因此,np.radians(180)不会向您π提供3.1415926535897931,而是sin(3.1415926535897931)

1.22e-16实际上就像x == y

那么,你怎么处理这个?

你必须弄清楚,或者至少猜测一下适当的绝对和/或相对误差范围,然后你写下来代替abs(y - x) < abs_bounds and abs(y-x) < rel_bounds * y

y

(这也意味着您必须组织计算,以使相对误差相对于x而不是y更大。在您的情况下,因为0是常量{ {1}},这是微不足道的 - 只是向后做。)

Numpy提供了一个函数,可以在整个数组中为您执行此操作allclose

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)

那么,你怎么知道正确的界限是什么?在SO答案中没有办法教你足够的错误分析。维基百科上的Propagation of uncertainty提供了高级概述。如果你真的没有线索,你可以使用默认值,1e-5相对和1e-8绝对值。

答案 1 :(得分:1)

遇到同样的问题,

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不会丢失太多信息。正如您可以想到的,舍入函数将舍弃5位数字后的值。

答案 2 :(得分:0)

一种解决方案是在计算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。

答案 3 :(得分:0)

尝试...将低于给定的微小值的任何东西都归零...

import numpy as np

def zero_tiny(x, threshold):
    if (x.dtype == complex):
        x_real = x.real
        x_imag = x.imag
        if (np.abs(x_real) < threshold): x_real = 0
        if (np.abs(x_imag) < threshold): x_imag = 0 
        return x_real + 1j*x_imag
    else:
        return  x if (np.abs(x) > threshold) else 0

value = np.cos(np.pi/2)
print(value)
value = zero_tiny(value, 10e-10)
print(value)

value = np.exp(-1j*np.pi/2)
print(value)
value = zero_tiny(value, 10e-10)
print(value)

答案 4 :(得分:-1)

简单。

np.sin(np.pi).astype(int)
np.sin(np.pi/2).astype(int)
np.sin(3 * np.pi / 2).astype(int)
np.sin(2 * np.pi).astype(int)

返回

0
1
0
-1

答案 5 :(得分:-3)

问题不在于pi的舍入误差。 请注意,余弦不会出现问题:

    In [2]: np.sin(np.pi)
    Out[2]: 1.2246467991473532e-16  != 0.
    In [3]: np.cos(np.pi)
    Out[3]: -1.0                    == -1.

问题更加复杂。它与处理器内部pi的精度有关。这是在这里发现和解释的: https://randomascii.wordpress.com/2014/10/09/intel-underestimates-error-bounds-by-1-3-quintillion/