Python余弦函数精度

4 投票
2 回答
8211 浏览
提问于 2025-04-17 16:05

从数学上我们知道,90度角的余弦值是0,但在Python中,它的值稍微大于0。

import math
math.cos(math.radians(90))
6.123233995736766e-17

那么,Python和数字“0”之间到底发生了什么呢?

2 个回答

6

正如Dietrich所指出的,内置的数学包使用的是数值近似来计算三角函数——比如说,π(圆周率)是通过浮点数来表示的,有一定的精度。不过,Python还有很多不错的包可以进行符号计算,比如Sympy,如果你想要更精确的计算,这个包很简单易用。

考虑一下:

import math
math.cos( 3*math.pi/2 )
# Outputs -1.8369701987210297e-16

与之相比

import sympy
sympy.cos( 3*sympy.pi/2 ) 
# Outputs 0

其实这种情况并不多,而且使用sympy的速度要慢得多。我测试过我的电脑在五秒钟内用math能计算多少次余弦,而用sympy则少得多,结果是math能计算38倍的次数。这要看你需要什么了。

7

跟我说:

计算机无法处理真实数字。

Python使用的是双精度IEEE浮点数,这种格式可以精确到53个二进制位,但它的数值范围是有限的。因为π/2是一个无理数,所以计算机会把它四舍五入到最接近的可以表示的数字(或者说是一个接近的可表示数字——有些操作的四舍五入是准确的,有些则会有超过1/2 ULP的误差)。

所以,你其实并没有让计算机计算cos(π/2),你实际上是让它计算cos(π/2+ε),这里的ε就是计算π/2时产生的舍入误差。然后结果还会再进行一次四舍五入。

为什么Excel(或其他程序)能显示正确的结果?

可能性1:这个程序进行的是符号计算,而不是数值计算。这种情况适用于像Mathematica和Maxima这样的程序,而不是Excel。

可能性2:这个程序可能在隐藏数据(最有可能)。Excel只会显示你要求的数字,比如:

>>> '%.10f' % math.cos(math.radians(90))
'0.0000000000'

Python有一个经过精细调校的函数,用于打印浮点数,以确保它们在文本和数字之间转换时不会丢失精度。这意味着Python默认打印的数字位数比例如printf要多。

可能性3:你使用的程序可能发生了两个舍入误差,结果相互抵消了。

撰写回答