You are using the Machin formula with the Taylor serie expansion for Arctan. It should give you about 1.4 digits of precision for each "cycle" (see here). You can't "shortcut" the calculation of the Taylor serie. You can speed-up a little the program removing the IEnumerable<BigInteger>
part and simply returning the nth iteration (the yield
instruction has a cost) and by changing the BigInteger.Pow
with a fixed multiplication. But the calculation will still be made iteratively. There is no known way for calculating PI with a precision of n digits in O(1) time.
Note that there are algorithms (see the wiki) that converge in a smaller number of cycles, but I'm not sure if they converge in a smaller number of operations (their cycles are much more complex).
An optimized version of the code:
public static BigInteger GetPi2(int digits, int iterations)
{
return 16 * ArcTan1OverX2(5, digits, iterations)
- 4 * ArcTan1OverX2(239, digits, iterations);
}
public static BigInteger ArcTan1OverX2(int x, int digits, int iterations)
{
var mag = BigInteger.Pow(10, digits);
var sum = BigInteger.Zero;
bool sign = true;
int imax = 1 + (2 * iterations);
int xsquared = x * x;
BigInteger pow = x;
for (int i = 1; i <= imax; i += 2)
{
if (i != 1)
{
pow *= xsquared;
}
var cur = mag / (pow * i);
if (sign)
{
sum += cur;
}
else
{
sum -= cur;
}
sign = !sign;
}
return sum;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…