简体   繁体   English

无法让BBP公式在nodejs中工作

[英]Can't get BBP formula to work in nodejs

I've been trying to make a little program that can compute the n-th digit of pi. 我一直试图制作一个可以计算pi的第n位数的小程序。

After a few searches I've found that the most common formula is the BBP formula, wich is n-th digit = 16^-n[4/(8n + 1)-2/(8n + 4)-1/(8n + 5)-1/(8n + 6)]. 经过几次搜索,我发现最常见的公式是BBP公式,它是第n位= 16 ^ -n [4 /(8n + 1)-2 /(8n + 4)-1 /(8n) + 5)-1 /(8n + 6)]。

The output is in base 16. 输出位于16位。

My code is the following: 我的代码如下:

function run(n) {
    return Math.pow(16, -n) * (4 / (8 * n + 1) - 2 / (8 * n + 4) - 1 / (8 * n + 5) - 1 / (8 * n + 6));
}

function convertFromBaseToBase(str, fromBase, toBase) {
    var num = parseInt(str, fromBase);
    return num.toString(toBase);
}


for (var i = 0; i < 10; i++) {
    var a = run(i);
    console.log(convertFromBaseToBase(a, 16, 10));
}

So far, my output is the following: 到目前为止,我的输出如下:

1:3
2:0
3:0
4:0
5:1
6:7
7:3
8:1
9:7
10:3

Obviously, these are not the 10 first digits of PI. 显然,这些不是PI的10个第一位数。 My understanding is that values get rounded too often and that causes huge innacuracy in the final result. 我的理解是,价值观过于频繁,导致最终结果造成巨大的空洞现象。

However, I could be wrong, that's why I'm here to ask if I did anything wrong or if it's nodejs's fault. 但是,我可能是错的,这就是为什么我在这里问我是否做错了什么或者是不是nodejs的错。 So I would loove if one of you guys have the answer to my problem! 如果你们其中一个人能解决我的问题,我会很乐意!
Thanks!! 谢谢!!

Unfortunately, 4/(8n + 1) - 2/(8n + 4) - 1/(8n + 5) - 1/(8n + 6) does not directly return the Nth hexadecimal digit of pi. 不幸的是, 4/(8n + 1) - 2/(8n + 4) - 1/(8n + 5) - 1/(8n + 6)不直接返回pi的第N个十六进制数字。 I don't blame you, I made the same assumption at first. 我不怪你,我起初做了同样的假设。 Although all the terms do indeed sum to pi, each individual term does not represent an individual hexadecimal digit. 虽然所有的条款确实总和为P1,每个单独的术语并不代表一个单独的十六进制数字。 As seen here , the algorithm must be rewritten slightly in order to function correctly as a "digit spigot". 正如所看到这里 ,算法必须稍加以作为“数字轴颈”正常工作改写。 Here is what your new run implementation ought to look like: 以下是您的新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"

Additionally, your convertFromBaseToBase function is more complicated than it needs to be. 此外,您的convertFromBaseToBase函数比它需要的更复杂。 You have written it to accept a string in a specific base, but it is already being passed a number (which has no specific base). 您已编写它以接受特定基础中的字符串,但它已经传递了一个数字(没有特定的基数)。 All you should really need is: 你真正需要的只是:

for (var i = 0; i < 10; i++) {
    var a = run(i);
    console.log(a.toString(16));
}

Output: 输出:

3
2
4
3
f
6
a
8
8
8

I have tested this code for the first 30 hexadecimal digits of pi, but it might start to return inaccurate results once Math.pow(16, d - 1 - k) grows beyond Number.MAX_SAFE_INTEGER , or maybe earlier for other reasons. 我已经测试了这个代码用于pi的前30个十六进制数字,但是一旦Math.pow(16, d - 1 - k)增长超过Number.MAX_SAFE_INTEGER ,它可能会开始返回不准确的结果,或者由于其他原因可能更早。 At that point you may need to implement the modular exponentiation technique suggested in the Wikipedia article. 此时,您可能需要实现Wikipedia文章中建议的模幂运算技术。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM