c# – 使用倒数平方和计算PI

前端之家收集整理的这篇文章主要介绍了c# – 使用倒数平方和计算PI前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要使用以下公式以预定义的精度计算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;
}

所以这是正确的,但我遇到了效率问题.精度值为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)= 10,000,000

你可以说你离开了,过于频繁地循环而没有提高过去9999万次迭代的结果的准确性.

是时候谈论真正的问题,太糟糕了,你没有解释你是如何得到如此严重错误的算法.但是你肯定在测试你的代码时发现它只是不太擅长计算pi的更精确的值.所以你想通过更频繁地迭代,你会得到更好的结果.

请注意,在此肘部测试中,您能够以足够的精度计算添加量也非常重要.我故意舍入数字,好像它是在能够执行5位精度的加法的机器上计算的.无论你做什么,结果都不会比5位更精确.

您在代码中使用double类型.由处理器直接支持,它没有无限的精度.您需要记住的唯一规则是使用double的计算永远不会比15位精确.同时记住浮动规则,它永远不会比7位数更精确.

因此,无论您通过什么样的价值,结果都不会比15位精确.这根本没用,你已经将pi的值精确到15位数.这是Math.Pi

解决这个问题需要做的一件事是使用精度高于double的类型.实际上,它需要是一种具有任意精度的类型,它至少需要与您传递的预定值一样准确.这种类型在.NET框架中不存在.找到一个可以为你提供一个库的库是SO的common question.

猜你在找的C#相关文章