int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5; for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a, f[b]=d%--g,d/=g--,--b;d*=b);}
#include<stdio.h> int a = 10000, b, c = 2800, d, e, f[2801], g; main() { for (int i = 0; i < c; i++) { f[i] = a / 5; } while (c != 0) { d = 0; g = c * 2; b = c; while (1) { d += f[b] * a; g--; f[b] = d % g; d /= g; g--; b--; if (b == 0) break; d *= b; } c -= 14; printf("%.4d", e + d / a); e = d % a; } }
#include<stdio.h> int b, c = 2800, d, e, f[2801]; main() { for (int i = 0; i < c; i++) { f[i] = 2000; } while (c != 0) { b = c; d = f[b] * 10000; f[b] = d % (b * 2 - 1); d /= b * 2 - 1; b--; while (1) { d = d * b + f[b] * 10000; f[b] = d % (b * 2 - 1); d = d / (b * 2 - 1); b--; if (b == 0) break; } c -= 14; printf("%.4d", e + d / 10000); e = d % 10000; } }
不过,即使是这样,这段代码还是让人看得很迷糊。我们不妨开个挂,进行倒推吧。 我们来看看这段代码的数学对应。这是一个计算的公式: 可以进一步写为 根据维基百科的相关内容,该公式最早似乎由牛顿推出,而 Wolfram 收录的一个变式则写明作者是 Beeler 等人(参见 PiFormulas)。 在这个迭代中,我们需要不断地生成形如的分式。对应于展开后的代码,不难发现 g 就是分母,而 b 则是分子。 当然,这还不是足够的。一个重要的问题是如何在逐次迭代中将误差进行传递,以实现任意精度的计算。整个程序中的唯一一个关系到输出的 printf 函数,每次会输出四位整数。那么 c -= 14 又是怎么来的呢?我们注意到,而,,这些「神秘数字」就都说得通了。每次循环用 14 项获得 4 位精确的值,它们是一个八位整数的前四位,因此需要模 10000;然后将后四位乘以 10000,代入下一次循环。