我一直试图制作一个可以计算pi的第n位的小程序。
经过几次搜索,我发现最常见的公式是BBP公式,第n位= 16 ^ -n [4 /(8n + 1)-2 /(8n + 4) -1 /(8n + 5)-1 /(8n + 6)]。
输出位于16位。
我的代码如下:
1:3
2:0
3:0
4:0
5:1
6:7
7:3
8:1
9:7
10:3
到目前为止,我的输出如下:
{{1}}
显然,这些不是PI的10个第一位数。 我的理解是,价值观过于频繁,导致最终结果造成巨大的空洞现象。
然而,我可能是错的,这就是为什么我在这里问我是否做错了什么或者它是否是错误的。如果你们其中一个人能解决我的问题,我会很乐意! 谢谢!
答案 0 :(得分:4)
不幸的是,4/(8n + 1) - 2/(8n + 4) - 1/(8n + 5) - 1/(8n + 6)
不会直接返回pi的第N个十六进制数字。我不怪你,我起初做了同样的假设。虽然所有术语确实总和到pi,但每个单独的术语不表示单个十六进制数字。如here所示,必须稍微重写算法才能正确地作为“数字插口”运行。以下是您的新run
实现应该是什么样的:
/**
Bailey-Borwein-Plouffe digit-extraction algorithm for pi
<https://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula#BBP_digit-extraction_algorithm_for_.CF.80>
*/
function run(n) {
var partial = function(d, c) {
var sum = 0;
// Left sum
var k;
for (k = 0; k <= d - 1; k++) {
sum += (Math.pow(16, d - 1 - k) % (8 * k + c)) / (8 * k + c);
}
// Right sum. This converges fast...
var prev = undefined;
for(k = d; sum !== prev; k++) {
prev = sum;
sum += Math.pow(16, d - 1 - k) / (8 * k + c);
}
return sum;
};
/**
JavaScript's modulus operator gives the wrong
result for negative numbers. E.g. `-2.9 % 1`
returns -0.9, the correct result is 0.1.
*/
var mod1 = function(x) {
return x < 0 ? 1 - (-x % 1) : x % 1;
};
var s = 0;
s += 4 * partial(n, 1);
s += -2 * partial(n, 4);
s += -1 * partial(n, 5);
s += -1 * partial(n, 6);
s = mod1(s);
return Math.floor(s * 16);
}
// Pi in hex is 3.243f6a8885a308d313198a2e037073...
console.log(run(0) === 3); // 0th hexadecimal digit of pi is the leading 3
console.log(run(1) === 2);
console.log(run(2) === 4);
console.log(run(3) === 3);
console.log(run(4) === 15); // i.e. "F"
此外,您的convertFromBaseToBase
功能比它需要的更复杂。您已编写它以接受特定基础中的字符串,但它已经传递了一个数字(没有特定的基数)。你真正需要的只是:
for (var i = 0; i < 10; i++) {
var a = run(i);
console.log(a.toString(16));
}
输出:
3
2
4
3
f
6
a
8
8
8
我已经针对pi的前30个十六进制数字测试了此代码,但是一旦Math.pow(16, d - 1 - k)
增长超过Number.MAX_SAFE_INTEGER
,或者由于其他原因可能更早,它可能会开始返回不准确的结果。此时,您可能需要实现维基百科文章中建议的模幂运算技术。