Search code examples
javascriptc++pispigot-algorithm

JavaScript Pi Spigot Algorithm not working


I have translated the following C++ code:

#include <iostream>
using namespace std;
#define NDIGITS 100
#define LEN (NDIGITS/4+1)*14

long a[LEN];
long b;
long c = LEN;
long d;
long e = 0;
long f = 10000;
long g;
long h = 0;
int main(void) {
    cout<<b<<endl;
    for(; (b=c-=14) > 0 ;){
        for(; --b > 0 ;){
            d *= b;
            if( h == 0 )
                d += 2000*f;
            else
                d += a[b]*f;
            g=b+b-1;
            a[b] = d % g;
            d /= g;
        }
        h = printf("%ld",e+d/f);
        d = e = d % f;
    }
    getchar();
    return 0;
}

Into JavaScript:

function mod(n, m) {
    return ((m % n) + n) % n;
} // mod function to fix javascript modulo bug
function calculate(NDIGITS){
    var LEN = (NDIGITS / 4 + 1) * 14,
        out = "",
        a = [],
        b = 0,
        c = LEN,
        d = 0,
        e = 0,
        f = 10000,
        g = 0,
        h = 0;
    for( ; a.length != LEN; a.push(0));
    for( ; (b=c-=14) > 0 ; ){
        for(; --b > 0 ;){
            d *= b;
            if(h == 0)
                d += 2000*f;
            else
                d += a[b]*f;
            g=b+b-1;
            a[b] = mod(d, g);
            d /= g;
        };
        h = 4;
        out += e + d / f;
        d = e = mod(d, f);
    };
    return out;
};
calculate(100);

The problem is, the C++ (which is correct) output looks like this:

314159265358979323846264338327952884197169399375105820974944592307816406286208998628034825342117067

But the JavaScript (which is wrong) output looks like this:

3141.59265358979345928.3358757688158002.0385670499462603.1996016540431161.44919092773639662.2465149363658988.6127837844255865.38922090756173.61883094848226189.6324225085448150.3443440509899223.2179589088062808.1943642437717982.8973948575671840.86646781354151140.38694447211833938.5632867441137341.458720505086448.7384444661472807.14448220310268936.5521832735086764.9290682040381301.76585926509928223.4135991546457438.115065010927

Where did I mess up in my coding? Thanks for the help.


Solution

    1. JavaScript does floating point division.
    2. Arguments exchanged in modulo calculation function.

    Here is code that produces the same result as the C++ code provided for the given sample (100) digits:

    function mod(m, n) {
            return ((m % n) + n) % n;
    } // mod function to fix javascript modulo bug
    
    function calculate(NDIGITS) {
        var LEN = (NDIGITS / 4 + 1) * 14,
            out = "",
            a = [],
            b = 0,
            c = LEN,
            d = 0,
            e = 0,
            f = 10000,
            g = 0,
            h = 0;
    
        for (; a.length !== LEN; a.push(0));
        for (; (b = c -= 14) > 0;) {
            for (; --b > 0;) {
                d *= b;
                if (h === 0) {
                    d += 2000 * f;
                } else {
                    d += a[b] * f;
                }
                g = b + b - 1;
                a[b] = mod(d, g);
                d = Math.floor(d / g);
            }
            h = Math.floor(e + d / f);
            out += h;
            h = h.length;
            d = e = mod(d, f);
        }
        return out;
    }
    console.log(calculate(100));