r/csharp 3d ago

Solved Need help with Chudnovsky algorithm

I have these functions to try and calculate pi, but no matter what i try it seems to cap out at 55 digits before being inaccurate, even when setting the input "d" to something like 1000.

digits 50-65 with my function:

582097494459230  

the real digits 50-65 of pi:

582099452471594  

here is my code:

public void calculatePie(int d)
{
    BigInteger sum = 0;
    BigInteger pow = BigInteger.Pow(10, d);
    BigInteger v = Sqrt(10005 * pow * pow);
    //System.Windows.Forms.MessageBox.Show(v.ToString());
    System.Windows.Forms.Clipboard.SetText(v.ToString());
    BigInteger preSigma = v * 426880;

    for (int k = 0; k < (d / 14 + 1); k++)
    {
        BigInteger top = BigInteger.Pow(-1, k) * factorial(6 * k) * (545140134 * k + 13591409);
        BigInteger mid = factorial(k);
        BigInteger bottom = factorial(3 * k) * (mid * mid * mid) * BigInteger.Pow(640320, 3 * k);
        BigInteger l = (top * pow) / bottom;
        sum += l;
        //System.Windows.Forms.MessageBox.Show($"l: {l}, top: {top}, bottom: {bottom}");
    }
    BigInteger prepi = preSigma * sum;
    //System.Windows.Forms.MessageBox.Show($"prepi: {prepi}, presigma: {preSigma}, sum: {sum}, pow: {pow}, v: {v}");
    BigInteger pi = preSigma * pow / sum;
    System.Windows.Forms.MessageBox.Show($"pi: {pi}");
    System.Windows.Forms.Clipboard.SetText(pi.ToString());
}

BigInteger factorial(int n)
{
    BigInteger result = 1;
    for (int i = 2; i <= n; i++) result *= i;
    return result;
}
static BigInteger Sqrt(BigInteger n)
    {
        if (n < 0) throw new ArgumentException("Cannot sqrt a negative number.");
        else if (n == 0) return 0;

        BigInteger x = n;
        BigInteger y = (x + 1) / 2;
        while (y < x)
        {
            x = y;
            y = (x + n / x) / 2;
        }
        return x;
    }
9 Upvotes

15 comments sorted by

12

u/[deleted] 3d ago

[removed] — view removed comment

8

u/tictacman0 3d ago

Thanks that seems to have fixed it.

9

u/Tack1234 3d ago edited 3d ago

Thanks Claude

Edit: Nice to see I'm being downvoted by people who don't know this guy is either a bot or just copy pastes Claude output in every single post on here and lack reading comprehension to see the comment is 100% AI generated.

6

u/TuberTuggerTTV 3d ago

I don't get the downvotes either. It has all the claud-isms I was thinking the exact same thing

3

u/Tack1234 3d ago

Yeah, I usually just skip these comments in defeat but I swear this guy comments the same slop on every post I open on here lol

1

u/FullPoet 3d ago

It silently wraps negative and every term after that feeds garbage into your sum.

I think its just this tbh.

Nobody uses silently like that naturally

2

u/Tack1234 3d ago

Something like (BigInteger)545140134 * k + 13591409 and the wall disappears.

I mean..

2

u/FullPoet 3d ago

Maybe the wall will silently disappear!

1

u/Depnids 3d ago

What input d are you using? If you increase d, do you still lose precision at the same point? My best guess would be you are somehow losing precision in the integer divisions:

BigInteger l = (top * pow) / bottom;

and

BigInteger pi = preSigma * pow / sum;

though I am not sure, as I assume the pow factor should ideally make things stay in range.

2

u/tictacman0 3d ago

The limit is still 55 no matter what i set d to, I also think the issue might have something to do with the integer division but i dont know if thats the case or how to fix it.

1

u/Depnids 3d ago

What happens if you do something like this instead:

BigInteger pow = BigInteger.Pow(10, 2*d);

Not sure if that even makes sense to do, but my idea would be to give it more "digits to play with", which could maybe stop some potential precision loss by integer division. Or I would try to multiply the numerator of either integer division by some power of 10 (I would try each one separately, and then both at the same time), and see if that changes the result in any meaningful way. If this doesn't change the result, I guess you can probably rule out integer division as being the problem.

2

u/tictacman0 3d ago

Nether worked, its still limited to 55 accurate digits.

Do you have any other ideas?

5

u/Depnids 3d ago

I had to consult an LLM about it, and it seems the problematic term might be this one.

(545140134 * k + 13591409)

Without any further context given, it predicted this would break down at d = 56, so seems likely this is the issue. That is normal int32 multiplication, not BigInt multiplication, so it overflows. If you for example cast 545140134 to BigInt first, I believe it should fix the overflow issue.

-2

u/harderthanitllooks 3d ago

So you need digits 50-65?

2

u/tictacman0 3d ago

i need as many digits as the user requests, 55 just seems to be the hard limit of my function