Python中为什么np.sin(np.pi)的结果不为0?

import numpy as np

print(np.sin(np.pi))
print(np.sin(0.5*np.pi))

结果分别是
1.2246467991473532e-16
1.0
Python中为什么np.sin(np.pi)的结果不为0?

6 回复

这是浮点数精度导致的常见问题。np.pi 是π的近似值,np.sin() 计算时会产生微小的浮点误差。

import numpy as np

result = np.sin(np.pi)
print(f"np.sin(np.pi) = {result}")  # 输出约 1.2246467991473532e-16
print(f"是否接近0: {np.isclose(result, 0)}")  # 输出 True

实际值约 1.22e-16,非常接近0。这是IEEE 754浮点数标准的固有特性,所有编程语言都会遇到。

处理建议:

  1. 比较时用容差np.isclose(a, b)abs(a - b) < 1e-10
  2. 需要精确0时取整np.round(np.sin(np.pi), 12)

总结:用容差比较替代精确相等。

因为π不能用有限空间的浮点数表示,只是一个近似值,所以你只能得到一个很接近 0 的值,而不是 0
同理 tan(π/2)
这叫 Catastrophic Cancellation
这也是比较浮点数时不能用==的原因
至于为什么第二个可以输出 1.0,是因为前面的 1.0000…占据了有效数字位(双精度可以保证 15~16 个有效数字),使误差被舍去了

#2 又查了下资料发现 Catastrophic Cancellation 好像不是这个意思。。

因为 Numpy 主打数值计算,精度误差不可避免。希望 sin(pi) 是精确值可以考虑 Mathematica 或者 SymPy:

In [1]: import sympy

In [2]: sympy.pi
Out[2]: pi

In [3]: sympy.sin
Out[3]: sin

In [4]: sympy.sin(sympy.pi)
Out[4]: 0

至于为什么 pi/2 更准:

In [1]: 1.0 == 1.0
Out[1]: True

In [2]: 1.0 == 1.0+1e-16
Out[2]: True

In [3]: 1.0 == 1.0+1e-15
Out[3]: False

In [4]: 1.0 == 1.0+1e-16
Out[4]: True

In [5]: 1.0 == 1.0+1.2e-16
Out[5]: False

具体代码可以去查查
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ieee754/dbl-64/s_sin.c;hb=HEAD#l281

do_sin 函数里似乎用了麦克劳林级数。所以返回的都是近似值。

回到顶部