此C#代码会将Pi计算为我指定的任何长度。我希望能够从给定索引开始,而无需重新计算到该点。精度不是一个大问题,因为这是一个难题项目,但我确实需要此代码来重复生成相同的结果。它可以正常工作,但我还无法弄清楚如何针对起点进行修改。
//Looking to pass BigInteger to specify a starting index for continuation of calculating Pi
public static BigInteger GetPi(int digits, int iterations)
{
return 16 * ArcTan1OverX(5, digits).ElementAt(iterations)
- 4 * ArcTan1OverX(239, digits).ElementAt(iterations);
}
public static IEnumerable<BigInteger> ArcTan1OverX(int x, int digits)
{
var mag = BigInteger.Pow(10, digits);
var sum = BigInteger.Zero;
bool sign = true;
for (int i = 1; true; i += 2)
{
var cur = mag / (BigInteger.Pow(x, i) * i);
if (sign)
{
sum += cur;
}
else
{
sum -= cur;
}
yield return sum;
sign = !sign;
}
}
您正在将Machin公式与Arctan的Taylor扩展系列一起使用。对于每个“周期”,它应为您提供约1.4位数的精度(请参见此处)。您不能“简化”泰勒系列的计算。您可以稍微加快程序的速度,删除该IEnumerable<BigInteger>
部分,然后简单地返回第n次迭代(该yield
指令会产生成本),并通过BigInteger.Pow
使用固定的乘法来更改。但是计算仍将迭代进行。没有已知的方法可以在O(1)时间中以n位精度计算PI。
请注意,有一些算法(请参阅Wiki)以较少的周期收敛,但是我不确定它们是否以较少的操作收敛(它们的周期要复杂得多)。
代码的优化版本:
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;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句