sympy如何计算pi?

罗比克(G. Robic)

sympi计算pi的数值背景是什么?

我知道SymPy在后台使用了mpmath,这使得使用任意精度算术执行计算成为可能。这样,某些特殊常量(例如e,pi,oo)将被视为符号,并且可以任意精度求值。

但是Sympy如何确定小数位数?Sympy如何进行数字化处理?

弗雷德里克·约翰逊(Fredrik Johansson)

mpmath使用Chudnovsky公式(https://en.wikipedia.org/wiki/Chudnovsky_algorithm计算pi

Pi由一个无限级数近似,其项数减少了(1/151931373056000)^ n,因此每个项大约增加了14.18个数字。这使得容易选择多个项N,从而实现期望的精度。

实际计算是通过整数算术完成的:即,对于prec的精度,将计算pi * 2 ^(prec的近似值

这是从mpmath / libmp / libelefun.py(https://github.com/fredrik-johansson/mpmath/blob/master/mpmath/libmp/libelefun.py)中提取的代码

# Constants in Chudnovsky's series
CHUD_A = MPZ(13591409)
CHUD_B = MPZ(545140134)
CHUD_C = MPZ(640320)
CHUD_D = MPZ(12)

def bs_chudnovsky(a, b, level, verbose):
    """
    Computes the sum from a to b of the series in the Chudnovsky
    formula. Returns g, p, q where p/q is the sum as an exact
    fraction and g is a temporary value used to save work
    for recursive calls.
    """
    if b-a == 1:
        g = MPZ((6*b-5)*(2*b-1)*(6*b-1))
        p = b**3 * CHUD_C**3 // 24
        q = (-1)**b * g * (CHUD_A+CHUD_B*b)
    else:
        if verbose and level < 4:
            print("  binary splitting", a, b)
        mid = (a+b)//2
        g1, p1, q1 = bs_chudnovsky(a, mid, level+1, verbose)
        g2, p2, q2 = bs_chudnovsky(mid, b, level+1, verbose)
        p = p1*p2
        g = g1*g2
        q = q1*p2 + q2*g1
    return g, p, q

@constant_memo
def pi_fixed(prec, verbose=False, verbose_base=None):
    """
    Compute floor(pi * 2**prec) as a big integer.
    This is done using Chudnovsky's series (see comments in
    libelefun.py for details).
    """
    # The Chudnovsky series gives 14.18 digits per term
    N = int(prec/3.3219280948/14.181647462 + 2)
    if verbose:
        print("binary splitting with N =", N)
    g, p, q = bs_chudnovsky(0, N, 0, verbose)
    sqrtC = isqrt_fast(CHUD_C<<(2*prec))
    v = p*CHUD_C*sqrtC//((q+CHUD_A*p)*CHUD_D)
    return v

这只是普通的Python代码,只不过它依赖于一个额外的函数isqrt_fast()来计算大整数的平方根。MPZ是使用的大整数类型:gmpy.fmpz(如果可用),否则为Python的内置long类型。所述@constant_memo装饰缓存计算值(通常反复需要数值计算PI,因此是有意义的存储它)。

您可以看到它通过如下进行基数转换来计算pi:

>>> pi_fixed(53) * 10**16 // 2**53
mpz(31415926535897932)

快速建立Chudnovsky公式的关键技巧称为二进制拆分无限级数中的项满足小系数的递归关系(可以在bs_chudnovsky函数中ba == 1的情况下看到递归方程)。而不是顺序计算项,而是将总和重复分成两半。对这两个半部分进行递归评估,然后将结果合并。最后,一个人有两个大整数pq,使得该系列的前N个的总和恰好等于p / q注意,在二进制分割过程中没有舍入误差,这是该算法的一个很好的特性。只有在计算平方根并在最后进行除法时,才会进行四舍五入。

尽管有一些复杂的技巧可以进一步加快处理速度,但大多数以高精确度计算pi的快速程序都使用了非常相似的策略。

(注意:我是代码的作者。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何用sympy计算argmax?

来自分类Dev

如何用sympy计算argmax?

来自分类Dev

Python-Sympy:如何计算谎言导数

来自分类Dev

Python-Sympy:如何计算谎言导数

来自分类Dev

如何使用Sympy计算Lambda表达式的导数?

来自分类Dev

How does sympy calculate pi?

来自分类Dev

计算机如何才能确定确定的PI?

来自分类Dev

如何使用Rayon进行PI的并行计算

来自分类Dev

如何从给定的偏移量计算Pi小数?

来自分类Dev

如何将最初使用 sympy.statistics 编写的 Normal/cdf() 计算转换为使用 sympy.stats?

来自分类Dev

计算Pi Java程序

来自分类Dev

Python pi计算?

来自分类Dev

用Java计算Pi

来自分类Dev

计算 PI (OverflowException)

来自分类Dev

如何使用sympy计算两个多边形的相交面积?

来自分类Dev

用php计算pi的正弦

来自分类Dev

关于PI计算的作业帮助

来自分类Dev

使用特殊算法计算 PI

来自分类Dev

使用碰撞块计算pi时如何防止快速移动的物体通过静力学

来自分类Dev

如何在 Raspberry Pi 中使用我计算机的互联网连接?

来自分类Dev

如何查询sympy约束?

来自分类Dev

如何查询sympy约束?

来自分类Dev

用Sympy计算泰勒级数的多元函数

来自分类Dev

定义sympy函数导数的数值计算

来自分类Dev

使用sympy的latex()函数而不计算输入

来自分类Dev

将SymPy的计算减慢到更小的步骤

来自分类Dev

Sympy-从函数计算“隐含”值

来自分类Dev

使用Sympy计算Riemann-Liouville积分

来自分类Dev

用Sympy计算泰勒级数的多元函数