正如我在评论中提到的,加快速度的唯一方法是改变顺序。这是一个非常简单的方法,与欧拉变换相关(参见罗皮的链接):对于交替序列的和,创建一个由以下组成的新序列average每对连续的部分和。例如,给定交替序列
a0 -a1 +a2 -a3 +a4 ...
哪里所有的a
s 为正数,部分和的序列为:
s0=a0 s1=a0-a1 s2=a0-a1+a2 s3=a0-a1+a2-a3 s4=a0-a1+a2-a3+a4 ...
那么新的导出序列是:
(s0+s1)/2 (s1+s2)/2 (s2+s3)/2 (s3+s4)/2 ...
这通常可以更快地收敛 - 并且相同的想法可以应用于该序列。也就是说,创建另一个新序列,对以下各项进行平均that顺序。这可以无限期地进行。在这里我将把它提升一个层次:
from math import pi
def leibniz():
from itertools import count
s, x = 1.0, 0.0
for i in count(1, 2):
x += 4.0*s/i
s = -s
yield x
def avg(seq):
a = next(seq)
while True:
b = next(seq)
yield (a + b) / 2.0
a = b
base = leibniz()
d1 = avg(base)
d2 = avg(d1)
d3 = avg(d2)
for i in range(20):
x = next(d3)
print("{:.6f} {:8.4%}".format(x, (x - pi)/pi))
Output:
3.161905 0.6466%
3.136508 -0.1619%
3.143434 0.0586%
3.140770 -0.0262%
3.142014 0.0134%
3.141355 -0.0076%
3.141736 0.0046%
3.141501 -0.0029%
3.141654 0.0020%
3.141550 -0.0014%
3.141623 0.0010%
3.141570 -0.0007%
3.141610 0.0005%
3.141580 -0.0004%
3.141603 0.0003%
3.141585 -0.0003%
3.141599 0.0002%
3.141587 -0.0002%
3.141597 0.0001%
3.141589 -0.0001%
因此,仅仅 20 项之后,我们就已经将 pi 保留到了大约 6 位有效数字。基本莱布尼兹序列仍然正确约 2 位:
>>> next(base)
3.099944032373808
这是一个巨大的进步。这里的一个关键点是,基本莱布尼兹序列的部分和给出了在“太大”和“太小”之间交替的近似值。这就是为什么对它们进行平均更接近事实。派生序列也是如此(在“太大”和“太小”之间交替),因此对它们的项进行平均也有帮助。
当然,这都是手动的。您可能对严格的理由不感兴趣;-)