Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.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#_Numerical Methods - Fatal编程技术网

C# 为什么我计算pi数的函数是冻结的?

C# 为什么我计算pi数的函数是冻结的?,c#,numerical-methods,C#,Numerical Methods,我需要计算pi数字直到第15位,但我的函数冻结。我使用泰勒级数: 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;

我需要计算
pi
数字直到第15位,但我的函数冻结。我使用泰勒级数:

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;
}

我已经调试过了,但我不知道为什么。链接到

问题在于,算法的精度与所需的位数成指数关系。为了演示,我对您的代码做了一些修改,以便在得到越来越精确的结果之前跟踪迭代次数

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;
  } 
 
}
正如您所见,percision的每个额外数字需要10倍的迭代次数,因此15个数字需要10000000倍的时间才能得到8。

从公式中

|cur - prev| = 1 / (2n+1) + 1 / (2n-1)
您的函数应该正常工作,您只需等到第25000000000000个术语。有点耐心(只有几天)

但不能保证你最后能得到15个精确的数字



永远不要使用莱布尼茨公式。使用Machin的变体

decimal
用于精确表示以10为基数的数字,而以2为基数的数字不能以固定精度表示。你代表的是无理数,所以你真的不应该在这里使用它。它比以2为基数的浮点数慢得多。另外,当您只使用条件时,为什么要使用
for
循环而不是
while
循环?@Servy,是的,while循环更好:)我不知道在这种情况下为什么要使用for循环。@Servy,我使用
decimal
type来计算Euler数,但我的函数没有冻结。尝试跟踪迭代次数,然后使用较小的ε,如1e-2,然后是1e-3,注意迭代次数是2*10^n,其中n是ε中使用的精度位数。所以对于15,它是2,然后是15个零的迭代。太多了。如果每次迭代只需要一纳秒,那么大约需要23天。或者,如果每一个都打了1个勾号,那么仍然需要5个多小时才能完成。
|cur - prev| = 1 / (2n+1) + 1 / (2n-1)