【问题标题】:Python: Decimals with trigonometric functionsPython:带三角函数的小数
【发布时间】:2012-06-06 22:16:16
【问题描述】:

我有一个小问题,看看:

>>> 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,我也需要一个可以做到这一点的库。

【问题讨论】:

  • "我可以使用十进制吗?"不,Pi 是非理性的。
  • 相关的问题是:你打算用这个库来做什么?这将决定你是否真的需要符号计算,或者是否有一些不那么重量级的方法来做你想做的事。您真的应该阅读@Zhenya 答案上的“每个计算机科学家应该了解的关于浮点运算的知识”链接。
  • 其实你得到的答案是正确,因为math.pi是最接近pi的浮点数,而不是pi本身!如果需要,您应该再次阅读有关浮点运算的链接。
  • 拥有一个以度为单位返回参数的三角函数值的库对您有什么好处?尽管 sine(180º) 为零,但只有少数特殊参数的三角函数值是有理数(并且可以用浮点数表示)。几乎所有可表示浮点值的正弦值都不是可表示浮点值。因此,即使您使用度数,您也会遇到小错误,正如您观察到的(几乎)pi 的正弦值。因此,我们需要更多地了解您想要完成的工作,然后才能给您提供好的答案。

标签: python math floating-point decimal trigonometry


【解决方案1】:

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

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

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

【讨论】:

  • 我忘了谢谢你的回答。你太对了。如果 PI 不是“精确”值,我怎么能等待 sin(PI) 成为精确值?对不起,我好像太笨了。感谢您的回答!
【解决方案2】:

Pi 是一个irrational number,所以它不能用有限的位数精确表示。但是,您可以使用一些库进行符号计算,例如 sympy

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

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

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

并按如下方式使用:

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

【讨论】:

  • 这很漂亮,我不知道sympy 可以做到这一点。
【解决方案3】:

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

真的很值得。

【讨论】:

  • 我已经读过了。谢谢!我已经知道涉及浮点数的问题。这就是我问这个的原因。
【解决方案4】:

你也可以试试 gmpy 或 real

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

    gmpy.pi(256) 

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

    from real import pa,pi
    pa(pi)

【讨论】:

  • 对 pi 使用更精确的值会得到更精确的结果,但不一定会得到准确的结果。
【解决方案5】:

简答 - Decimal.cos() 和 Decimal.sin() 都可以从 Decimal.exp() 实现中实现,方法是将所有偶数项拆分为 cos() 函数,将所有奇数项拆分为 sin() 函数,并交替每个符号的符号这两个系列中的正负之间的术语。循环中无需更改,仅根据配置的精度计算 N 项 (Decimal.getcontext().prec)。

长答案 - Python decimal.Decimal 支持 exp() 函数,它只接受一个实数参数(与 R 语言中的 exp() 不同),并且仅根据配置的精度计算无限级数(decimal.Decimal.getcontext()。前)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多