给定一个正整数Ñ输出的第一总和Ñ的小数部分的十进制数字π Ñ。
输入和输出示例:
1→1
2→14
3→6
4→13
5→24
50→211
500→2305
5000→22852
不允许使用内置函数计算π位数或评估幂级数或连续分数。有标准漏洞。输入/输出可以采用方便的格式(stdin,stdout,功能输入/输出等)。
给定一个正整数Ñ输出的第一总和Ñ的小数部分的十进制数字π Ñ。
输入和输出示例:
1→1
2→14
3→6
4→13
5→24
50→211
500→2305
5000→22852
不允许使用内置函数计算π位数或评估幂级数或连续分数。有标准漏洞。输入/输出可以采用方便的格式(stdin,stdout,功能输入/输出等)。
Answers:
t=i=1L;k=n=input();f=2000*20**n;A=range(n+1)
for k in range(2,n):A=[(A[j-1]+A[j+1])*j>>1for j in range(n-k+1)];f*=k
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))
快约4倍的版本-206字节
t=i=1L;k=n=input();f=2000*20**n;A=[0,1]+[0]*n
for k in range(1,n):
f*=k
for j in range(-~n/2-k+1):A[j]=j*A[j-1]+A[j+1]*(j+2-n%2)
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))
输入来自标准输入。在第二个脚本中,n = 5000的输出大约需要14s(或在第一个脚本中需要60s)。
用法示例:
$ echo 1 | python pi-trunc.py
1
$ echo 2 | python pi-trunc.py
14
$ echo 3 | python pi-trunc.py
6
$ echo 4 | python pi-trunc.py
13
$ echo 5 | python pi-trunc.py
24
$ echo 50 | python pi-trunc.py
211
$ echo 500 | python pi-trunc.py
2305
$ echo 5000 | python pi-trunc.py
22852
使用的公式如下:
其中甲Ñ是Ñ 个 交替号,其可以被正式地定义为交替排列的数目上的一组尺寸的Ñ(也参见:A000111)。可替代地,该序列可以被定义为切线数和割线数(A 2n= S n,A 2n + 1= T n)的组成,其后更多。
随着n变大,小的校正因子c n迅速收敛到1,并由下式给出:
对于n = 1,这相当于评估Leibniz级数。近似π为10 ½,所需的项数可被计算为:
收敛(向上舍入)到17,尽管较小的n值需要更多。
为了计算A n,有几种算法,甚至是一个显式公式,但是所有算法都是n的二次方。我最初编码了Seidel算法的实现,但是它变得太慢而无法实用。每次迭代都需要存储一个附加项,并且这些项的大小会非常迅速地增加(“错误”的O(n 2)种类)。
第一个脚本使用最初由Knuth和Buckholtz给出的算法的实现:
对于所有k = 1..n 令T 1,k = 1
T的后续值由递归关系给出:
T n + 1,k = 1/2 [ (k-1)T n,k-1 +(k +1)T n,k + 1 ]
然后由T n,1给出一个n
(另请参阅:A185414)
尽管没有明确说明,该算法同时计算切线数和割线数。第二脚本使用该算法通过的变化Brent和齐默尔曼,其计算要么Ť或小号,取决于奇偶Ñ。改进是n / 2的二次方,因此〜4x速度改进。
对于采用二次收敛的π计算,我采用了类似的方法。最后一行采用pi的N次方并求和。N = 5000测试需要一分钟左右的时间。
from decimal import*
d=Decimal
N=input()
getcontext().prec=2*N
j=d(1)
h=d(2)
f=h*h
g=j/h
a=j
b=j/h.sqrt()
t=j/f
p=j
for i in bin(N)[2:]:e=a;a,b=(a+b)/h,(a*b).sqrt();c=e-a;t-=c*c*p;p+=p
k=a+b
l=k*k/f/t
print sum(map(int,`l**N`.split('.')[1][:N]))
一些测试:
$ echo 1 | python soln.py
1
$ echo 3 | python soln.py
6
$ echo 5 | python soln.py
24
$ echo 500 | python soln.py
2305
$ echo 5000 | python soln.py
22852
未经处理的代码:
from decimal import *
d = Decimal
N = input()
getcontext().prec = 2 * N
# constants:
one = d(1)
two = d(2)
four = two*two
half = one/two
# initialise:
a = one
b = one / two.sqrt()
t = one / four
p = one
for i in bin(N)[2:] :
temp = a;
a, b = (a+b)/two, (a*b).sqrt();
pterm = temp-a;
t -= pterm*pterm * p;
p += p
ab = a+b
pi = ab*ab / four / t
print sum(map(int, `pi ** N`.split('.')[1][:N]))
a=j
并p=j
以a=p=j
IIRC。也许。
s<>j^u+/*GHhyHy^TyQr*TQ0ZQT_y*QQQ
基于isaacg的答案。可能会打更多的高尔夫球。慢。
s<>j Digit sum of...
^
u Evaluate pi = 2 + 1/3*(2 + 2/5*(2 + 3/7*(2 + 4/9*(2 + ...))))
+
/
*GH
hyH
y^TyQ Except we generate a large integer containing 2n digits,
rather than a fraction.
r*TQ0 Experimentally verified that 10*n iterations will give enough
precision for 2n digits (# digits correct grows faster than 2n).
Z
Q To the nth power.
T_y*QQQ Get the last 2n^2 digits (all the fractional digits) and get the
first n fractional digits.