在Python中防止舍入为零

时间:2013-04-11 00:50:04

标签: python math rounding pi

我有一个程序用于使用Chudnovsky算法逼近pi,但是我的等式中的一个非常小的项保持舍入为零。

以下是算法:

import math
from decimal import *
getcontext().prec = 100

pi = Decimal(0.0)
C = Decimal(12/(math.sqrt(640320**3)))
k = 0
x = Decimal(0.0)
result = Decimal(0.0)
sign = 1
while k<10:
    r = Decimal(math.factorial(6*k)/((math.factorial(k)**3)*math.factorial(3*k)))
    s = Decimal((13591409+545140134*k)/((640320**3)**k))
    x += Decimal(sign*r*s)
    sign = sign*(-1)
    k += 1
result = Decimal(C*x)
pi = Decimal(1/result)


print Decimal(pi)

如果没有“十进制”术语,方程式可能更清晰。

import math

pi = 0.0
C = 12/(math.sqrt(640320**3))
k = 0
x = 0.0
result = 0.0
sign = 1
while k<10:
    r = math.factorial(6*k)/((math.factorial(k)**3)*math.factorial(3*k))
    s = (13591409+545140134*k)/((640320**3)**k)
    x += sign*r*s
    sign = sign*(-1)
    k += 1
result = C*x
pi = 1/result

print pi

问题在于“s”变量。对于k> 0,它总是变为零。例如在k = 1时,s应该等于大约2.1e-9,但它只是零。因为这个我的所有术语在第一个= 0之后。如何让python计算s的确切值而不是将其舍入为0?

4 个答案:

答案 0 :(得分:3)

尝试:

s = Decimal((13591409+545140134*k)) / Decimal(((640320**3)**k))

你正在做的算法是原生python - 通过允许Decimal对象执行你的除法,你应该消除你的错误。

在计算r时,您也可以这样做。

答案 1 :(得分:2)

几条评论。

如果您使用的是Python 2.x,/将返回整数结果。如果你想要一个十进制结果,你首先将至少一边转换为十进制。

math.sqrt()仅返回~16位精度。由于您的C值仅精确到16位,因此您的最终结果将精确到16位。

答案 2 :(得分:2)

如果您在Python 2.x中进行数学运算,那么您应该将这一行放在每个模块中:

from __future__ import division

这会改变除法运算符的含义,以便在需要时返回浮点数以给出(更接近)精确答案。 x / y如果intx都是y,则int的历史行为会返回__future__,这通常会迫使答案向下舍入。< / p>

如果需要,返回一个浮点数通常被认为是一种更好的方法来处理像Python这样鼓励鸭子打字的语言中的除法,因为你可以担心你的数字的而不是得到不同类型的不同行为。

在Python 3中,这实际上是默认的,但由于旧程序依赖于分区运算符的历史行为,因此感觉这种变化太过于向后 - 与Python 2不兼容。这就是您必须使用{{1}}导入明确启用它的原因。我建议总是在可能正在进行任何数学运算的任何模块中添加导入(或者只是任何模块,如果你可能会被打扰)。你几乎永远不会对它感到沮丧,但没有它,我必须追逐一些模糊不清的错误。

答案 3 :(得分:0)

我觉得's'的问题是所有术语都是整数,因此你在做整数数学。一个非常简单的解决方法是在分母中使用3.0。计算中只需要一个浮点数就可以返回一个浮点数。