C# 使用逆平方和计算PI
我需要使用以下公式以预定义的精度计算PI: 所以我最终得到了这个解决方案C# 使用逆平方和计算PI,c#,math,pi,C#,Math,Pi,我需要使用以下公式以预定义的精度计算PI: 所以我最终得到了这个解决方案 private static double CalculatePIWithPrecision(int presicion) { if (presicion == 0) { return PI_ZERO_PRECISION; } double sum = 0; double numberOfSumElements = Math.Pow(10, presicion
private static double CalculatePIWithPrecision(int presicion)
{
if (presicion == 0)
{
return PI_ZERO_PRECISION;
}
double sum = 0;
double numberOfSumElements = Math.Pow(10, presicion + 2);
for (double i = 1; i < numberOfSumElements; i++)
{
sum += 1 / (i * i);
}
double pi = Math.Sqrt(sum * 6);
return pi;
}
private静态双精度计算(int-presision)
{
如果(预测值==0)
{
返回PI_零_精度;
}
双和=0;
double numberOfSumElements=数学功率(10,预测+2);
for(双i=1;i
所以这是正确的,但我面对的问题是效率。它的速度非常慢,精度值为8或更高
有没有更好(更快)的方法用这个公式计算PI
double numberOfSumElements = Math.Pow(10, presicion + 2);
我将严格用实用的软件工程术语来讨论这个问题,避免在正式的数学中迷失方向。任何软件工程师都应该知道的实用技巧
首先观察代码的复杂性。执行所需的时间严格取决于此表达式。您已经编写了一个指数算法,您计算的值随着预测值的增加而迅速增加。你引用了一个令人不舒服的数字,8产生10^10,或者一个循环产生100亿次计算。是的,你注意到了,计算机开始用几秒钟的时间产生结果,不管它们有多快
指数算法很糟糕,它们的性能很差。对于阶乘复杂度O(n!)更高的情况,你只能做得更糟。否则,许多现实世界问题的复杂性就会增加
现在,这个表达真的准确吗?您可以使用一个实用的信封背面示例,通过“肘部测试”来实现这一点。让我们选择一个精度为5位数的目标,并写出:
1.0000 + 0.2500 + 0.1111 + 0.0625 + 0.0400 + 0.0278 + ... = 1.6433
可以看出,加法很快变小,收敛很快。你可以推断出,一旦你添加的下一个数字足够小,那么它对使结果更准确几乎没有作用。假设下一个数字小于0.00001,那么是时候停止尝试改进结果了
所以你会停在1/(n*n)=0.00001=>n*n=100000=>n=sqrt(100000)=>n~=316
您的表达式表示在10^(5+2)=10000000处停止
您可以看出,您已经走远了,循环太频繁了,并且在过去的9999万次迭代中没有提高结果的准确性
是时候谈谈真正的问题了,可惜你没有解释你是如何得到一个如此严重错误的算法的。但当测试代码时,您肯定发现它不太擅长计算更精确的pi值。所以你认为通过更频繁的迭代,你会得到更好的结果 请注意,在此弯头测试中,能够以足够的精度计算加法也是非常重要的。我故意将数字四舍五入,就好像它是在一台能够执行精度为5位数的加法的机器上计算出来的一样。无论你做什么,结果都不能超过5位数 您正在代码中使用双精度类型。由处理器直接支持,它没有无限的精度。你需要记住的一条也是唯一一条规则是,用double计算的精度永远不会超过15位。还要记住浮点数的规则,它的精度永远不会超过7位 因此,无论您将什么值传递给Presision,结果都可以永远比15位更精确。这一点都没有用,你已经有了精确到15位的pi值。这是数学
要解决这个问题,您需要做的一件事是使用一个比double更精确的类型。事实上,它需要是一个具有任意精度的类型,它至少需要与您传递的presicion值一样精确。此类类型在.NET framework中不存在。找到一个能为您提供一个的库是一件非常困难的事情。如果只执行一次,它是否真的太慢以至于有问题?请尝试在
中为语句使用int
。我怀疑在那里使用double会让你慢很多。@ScottHunter是的,它很慢。看看numberOfSumElements变量及其与精度的关系。@Sopuli建议使用int
循环变量,只要presicion
不超过8(否则Pow(10,presicion+2)
将溢出int
)。您还需要将sum+=
行上的1
更改为1.0
,以获得正确的结果,并将numberOfSumElements
更改为int
(在作业上进行适当的转换)以获得最大的好处。请阅读公式并为每个人编码。OP抱怨当精度>=8时循环速度慢,为此循环运行了10^10次!这是1000000000次迭代。当然,这很慢。