【问题标题】:Why my function that calculates pi number is freezing?为什么我的计算 pi 数的函数冻结了?
【发布时间】:2020-08-21 17:55:28
【问题描述】:

我需要计算 pi 直到第 15 位,但我的函数冻结了。我使用这个泰勒系列:

atan(x) = \sum_{n=0}^\infty \frac{(-1)^{n} \cdot x^{2n + 1}}{2n + 1}

而 x 等于 1。

还有我的功能:

public static decimal Pi()
{
   decimal curr = 4m, 
   prev = 0m,
   one = -1m,
   den = 3.0m;

   while (Math.Abs(curr - prev) > 1e-15m)
   {
      prev = curr;
      curr += 4.0m * one / den;
      one = -one;
      den += 2.0m;
   }
        
   return curr;
}

我已经调试过了,但我没有找到原因。链接到REPL

【问题讨论】:

  • decimal 用于精确表示以 10 为底的数字,而不能以固定精度以 2 为底表示的数字。你代表的是无理数,所以你真的不应该在这里使用它。它比以 2 为底的浮点数要慢 很多
  • 另外,当你只使用条件时,为什么要使用for 循环而不是while 循环?
  • @Servy,是的,while 循环更好 :) 我不知道为什么我在这种情况下使用 for 循环。
  • @Servy,我使用decimal 类型来计算欧拉数,但我的函数没有冻结。
  • 尝试跟踪迭代次数并使用较小的 epsilon(如 1e-2 然后 1e-3)并注意迭代次数为 2*10^n 其中 n 是精度位数您在 epsilon 中使用。因此,对于 15,它是 2,然后是 15 个零迭代。好多啊。如果每次迭代需要一纳秒,那将需要大约 23 天。或者,如果每一个都需要 1 个滴答声,它仍然需要 5 个多小时才能完成。

标签: c# numerical-methods


【解决方案1】:

问题在于该算法是您想要的精度位数的指数。为了证明我已经稍微更改了您的代码以跟踪迭代次数,然后我们才能获得越来越精确的结果

decimal curr = 4m, 
prev = 0m,
one = -1m,
den = 3.0m;

int i = 0;
decimal epsilon = 1;

while(true)
{
  prev = curr;
  curr += 4.0m * one / den;
  one = -one;
  den += 2.0m;
  
  i++;
  
  if(Math.Abs(curr - prev) <= epsilon)
  {
    Console.WriteLine(curr);
    Console.WritleLine(i);
    epsilon /= 10m;
  } 
 
}

这是达到 8 位精度后的结果。

3.4666666666666666666666666667
2
3.1891847822775947292439110472
20
3.1465677471829564012877876609
200
3.1420924036835276076022995132
2000
3.1416426510898869869000847891
20000
3.1415976535647933322124871234
200000
3.1415931535895432385563933310
2000000
3.1415927035897907384627370503
20000000
3.1415926585897932134626435385
200000000

如您所见,每增加一个精度数字需要 10 倍的迭代次数,因此 15 个数字将需要 10,000,000 次,因为它需要获得 8 个。

【讨论】:

    【解决方案2】:

    从公式,

    |cur - prev| = 1 / (2n+1) + 1 / (2n-1)
    

    您的函数应该可以正常工作,您只需要等到第 250,000,000,000,000 个术语。一点耐心(只有几天)。

    但不能保证你最终得到 15 个准确的数字。


    永远不要使用莱布尼茨的公式。使用 Machin 的变体。 https://en.wikipedia.org/wiki/Machin-like_formula

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-22
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 2012-10-18
      • 1970-01-01
      相关资源
      最近更新 更多