Chudnovsky 算法 python 不正确的小数

Chudnovsky algorithm python incorrect decimals

我的目标是在 Python 中得到 100.000 或 200.000 个正确的 Pi 小数。为此,我尝试使用 Chudnovsky 算法,但在此过程中遇到了一些问题。

首先,程序只给了我 29 个字符,而不是我要测试正确性的 50 个。我知道这是一个小问题,但我不明白我做错了什么。

其次,只有前14位小数是正确的。在那之后,我开始根据互联网上几乎所有的 Pi 数字得到不准确的 Pi 小数。如何获得更正确的小数位数?

最后,我如何让我的代码 运行 在我拥有的所有 4 个线程上?我试过使用 Pool,但它似乎不起作用。 (用 Windows 任务管理器检查过)

这是我的代码:

from math import *
from decimal import Decimal, localcontext
from multiprocessing import Pool
import time
k = 0
s = 0
c = Decimal(426880*sqrt(10005))

if __name__ == '__main__':
    start = time.time()

    pi = 0

    with localcontext() as ctx:
        ctx.prec = 50

        with Pool(None) as pool:
            for k in range(0,500):
                m = Decimal((factorial(6 * k)) / (factorial(3 * k) * Decimal((factorial(k) ** 3))))
                l = Decimal((545140134 * k) + 13591409)
                x = Decimal((-262537412640768000) ** k)
                subPi = Decimal(((m*l)/x))
                s = s + subPi


    print(c*(s**-1))

    print(time.time() - start)

除了@mark-dickinson 在评论中讨论和提出的小细节外,我想我已经修复了多线程,但我还没有机会测试它,如果它工作正常请告诉我

更新: 第 28 位之后的问题是由于在 decimal context 更改之前分配了 sq 和 c。更改 context 精度后重新分配它们的值解决了问题

from math import *
import decimal
from decimal import Decimal, localcontext
from multiprocessing import Pool
import time
k = 0
s = 0
sq = Decimal(10005).sqrt() #useless here
c = Decimal(426880*sq) #useless here

def calculate():
    global s, k
    for k in range(0,500):
        m = Decimal((factorial(6 * k)) / (factorial(3 * k) * Decimal((factorial(k) ** 3))))
        l = Decimal((545140134 * k) + 13591409)
        x = Decimal((-262537412640768000) ** k)
        subPi = Decimal((m*l)/x)
        s = s + subPi
        
    print(c*(s**-1))

if __name__ == '__main__':
    start = time.time()

    pi = 0

    decimal.getcontext().prec = 100 #change the precision to increse the result digits

    sq = Decimal(10005).sqrt()
    c = Decimal(426880*sq)

    pool = Pool()
    result = pool.apply_async(calculate)
    result.get()

    print(time.time() - start)