2
\$\begingroup\$

Looking for style and speed review

π PI
An estimate is \$\frac{4}{1} - \frac{4}{3} + \frac{4}{5} - \frac{4}{7} + \frac{4}{9} - \frac{4}{11} + \frac{4}{13} - \frac{4}{15} + \frac{4}{17} \$...

The average of the last two is the current best estimate

Is the estimate correct to a certain number of digits

The answer has to be between the + and - or the algorithm would just be wrong

Have to worry about rounding error so I just don't report last 3 digits

Test

decimal pi;
sw.Restart();
int count = 4;
foreach (decimal d in PI4b(24))
{
    Console.WriteLine("ms {0}  digits {1}",  sw.ElapsedMilliseconds.ToString("N0"), count);
    Console.WriteLine(d);
    Console.WriteLine("");
    count++;

}

Code

public static IEnumerable<decimal> PI4b(int digits)
{
    if (digits < 4)
    {
        digits = 4;
    }
    else if (digits > 24)
    {
        digits = 24;
    }

    decimal piAcual = 3.1415926535897932384626433832m;  // 28 after decimal
    Decimal pi = 4m, iteration = 3m, piAvg = 0m;
    Decimal piLast = 10000m;
    int match = 0;
    int matchMax = 10000;
    for (int curDigits = 4; curDigits <= digits; curDigits++)
    {
        do
        {
            piLast = piAvg;
            pi -= 4m / iteration;
            piAvg = pi;
            iteration += 2m;
            pi += 4m / iteration;
            piAvg = (pi + piAvg) / 2m;
            iteration += 2m;
            if (Decimal.Round(piAvg, curDigits + 2) == Decimal.Round(piLast, curDigits + 2))
            {
                match++;
            }
            else
            {
                if (matchMax < match)
                {
                    matchMax = match; 
                }
                match = 0;
            }
        } while (match < 2 * matchMax);
        if (Decimal.Round(piAvg, curDigits) != Decimal.Round(piAcual, curDigits))
        {
            Debug.WriteLine(Decimal.Round(piAcual, curDigits));
            Debug.WriteLine(Decimal.Round(piAvg, curDigits));
            throw new Exception("wrong answer");
        }
        match = 0;
        yield return Decimal.Round(piAvg, curDigits);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.