Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用逆平方和计算PI_C#_Math_Pi - Fatal编程技术网

C# 使用逆平方和计算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

我需要使用以下公式以预定义的精度计算PI:

所以我最终得到了这个解决方案

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次迭代。当然,这很慢。