Python:三角函数中的小数

5
我遇到了一个小问题,请看下面:

我有一个小问题,请看:

>>> import math
>>> math.sin(math.pi)
1.2246467991473532e-16

这不是我在微积分课上学到的(实际上是0)

那么,我的问题是:

我需要使用Python进行一些重量级三角函数计算。有哪个库可以让我得到正确的值?

我可以使用Decimal吗?

编辑:

对不起,我意思是其他的事情。

我想要的是一些方法来做:

>>> awesome_lib.sin(180)
0

或者这个:
>>> awesome_lib.sin(Decimal("180"))
0

我需要一款执行良好的三角函数计算库。众所周知,sin 180°等于0,我需要一款也能实现这点的库。


2
我可以使用十进制吗?不行。圆周率是无理数。 - Ignacio Vazquez-Abrams
3
相关问题是:你到底打算用这个库来做什么?这将决定你是否真正需要符号计算,或者是否有一些更轻量级的方法可以实现你想要的功能。你真的应该阅读@Zhenya答案中提供的关于浮点算术的“每个计算机科学家都应该知道的知识”链接。 - comingstorm
实际上,你得到的答案是正确的,因为math.pi是最接近pi的浮点数,但不是pi本身!如果需要,您应该再次阅读有关浮点算术的链接。 - jorgeca
1
拥有一个返回以度为单位的三角函数参数值的库对你有什么好处呢?尽管正弦(180º)为零,但只有少数特殊参数具有有理三角函数值(并且可表示为浮点数)。几乎每个可表示为浮点数的正弦都不是可表示为浮点数的。因此,即使使用度数,您也会遇到小误差,就像您观察到的(几乎)pi的正弦一样。因此,在我们能够给出好的答案之前,我们需要更多地了解您想要实现的目标。 - Eric Postpischil
5个回答

15

1.2246467991473532e-16接近于0,小数点和第一个有效数字之间有16个零 -- 就像3.1415926535897931(即math.pi的值)接近于圆周率一样。这个答案在小数点后16位是正确的!

所以如果你想让sin(pi)等于0,只需将其四舍五入到合理的小数位数。对我来说,15位看起来很不错,而且对于任何应用程序来说应该足够了:

print round(math.sin(math.pi), 15)

我忘了感谢你的回答。你说得太对了。如果PI不是一个“精确”的值,那么我怎么能期待sin(PI)是一个精确的值呢?很抱歉似乎我太蠢了。感谢你的回答! - santiagobasulto

13

Pi是一个无理数,因此不能用有限数量的比特表示。但是,您可以使用一些符号计算库,例如sympy

>>> sympy.sin(sympy.pi)
0

关于你问题的第二部分,如果你想使用度数而不是弧度,你可以定义一个简单的转换函数。

def radians(x):
    return x * sympy.pi / 180

并按以下方式使用:

>>> sympy.sin(radians(180))
0

这很棒,我不知道 sympy 可以做到这一点。 - kindall

7

1
我已经阅读了。谢谢!我已经知道浮点数的问题。这就是为什么我在问这个问题。 - santiagobasulto

0

简短回答 - 通过将所有偶数项拆分到cos()函数中,将所有奇数项拆分到sin()函数中,并在这两个序列中交替改变每个项的正负号,可以从Decimal.exp()实现中同时实现Decimal.cos()和Decimal.sin()。循环中不需要进行任何更改,它仅基于配置的精度(Decimal.getcontext().prec)计算N个项。

详细回答 - Python decimal.Decimal支持exp()函数,该函数仅接受实数参数(与R语言中的exp()不同),并仅根据配置的精度(decimal.Decimal.getcontext().prec)计算无限级数的项数。

目前,偶数项计算cosh(),奇数项计算sinh()。它们的总和作为exp()的结果返回。如果在每个序列内修改每个项的符号以在正数和负数之间交替变化,则偶数项序列将计算cos(),奇数项序列将计算sin()。

此外,像R语言一样,这种改变可以使Decimal.exp()支持复杂参数,以便exp(1j*x)可以返回Decimal.cos(x) + 1j * Decimal.sin(x)。


0

你也可以尝试使用gmpy或real。

在gmpy中,你可以明确指定精度:

    gmpy.pi(256) 

在 real.py 中,您可以使用 pa() 函数:

    from real import pa,pi
    pa(pi)

2
使用更精确的π值将会得到更精确的结果,但这并不一定会导致一个准确的结果。 - Ignacio Vazquez-Abrams

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