5

我有一个小问题,看看:

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

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

所以,现在,我的问题:

我需要用 Python 执行一些繁重的三角计算。我可以使用什么库来获取正确的值?

我可以使用十进制吗?

编辑:

对不起,我的意思是另外一回事。

我想要的是某种方法:

>>> awesome_lib.sin(180)
0

或这个:

>>> awesome_lib.sin(Decimal("180"))
0

我需要一个执行良好三角学的库。每个人都知道 sin 180° 是 0,我也需要一个可以做到这一点的库。

4

5 回答 5

15

1.2246467991473532e-16接近 0——小数点和第一个有效数字之间有 16 个零——就像3.1415926535897931(的值math.pi)接近 pi。答案正确到小数点后十六位!

因此,如果您想sin(pi)等于 0,只需将其四舍五入到合理的小数位数即可。15 对我来说看起来不错,对于任何应用程序都应该足够了:

print round(math.sin(math.pi), 15)
于 2012-06-01T16:42:40.643 回答
12

Pi 是一个无理数,因此无法使用有限的位数精确表示。但是,您可以使用一些库进行符号计算,例如sympy

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

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

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

并按如下方式使用它:

>>> sympy.sin(radians(180))
0
于 2012-06-01T16:45:17.263 回答
7

如果你发现结果出乎意料,我敢建议你看看这篇文章: What Every Computer Scientist Should Know About Floating-Point Arithmetic

这真的很值得。

于 2012-06-01T16:50:09.637 回答
0

你也可以试试 gmpy 或 real

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

    gmpy.pi(256) 

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

    from real import pa,pi
    pa(pi)
于 2012-06-01T17:06:28.493 回答
0

简短答案 - Decimal.cos() 和 Decimal.sin() 都可以从 Decimal.exp() 实现中实现,方法是将所有偶数项拆分为 cos() 函数,将所有奇数项拆分为 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)。

于 2016-11-11T07:03:13.720 回答