2008-09-02 56 views
22

如何使用C#计算PI的值?如何计算C#中的PI?

我在想这是通过递归函数,如果是的话,它会是什么样子,并且有没有任何数学方程来支持它?

我对表现并不是太挑剔,主要是从学习的角度去看待它。

+0

[这个问题](http://stackoverflow.com/questions/19/fastest-way-to -pi-value-of-pi)从算法角度来看有很多好的解决方案。我不认为将它们中的一个适配到c#很难。 – 2008-09-02 12:40:57

回答

40

如果你想递归:

PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...)))) 

这会成为一些重写后:

PI = 2 * F(1); 

与F(I):

double F (int i) { 
    return 1 + i/(2.0 * i + 1) * F(i + 1); 
} 

艾萨克·牛顿(你可以有听说过他之前;))想出了这个诀窍。 请注意,我遗漏了结束条件,以保持简单。在现实生活中,你需要一个。

+0

另外,你是否需要返回一个值? – JFA 2013-10-17 03:39:53

+3

@jack它没有终止条件或返回值。如果你想创建一个完整的工作示例,我建议你发布一个新的答案。请参阅回答中的注释`请注意,我忽略了最终条件,以保持简单。在现实生活中,你需要一个.` – dcaswell 2013-10-17 03:53:02

+4

这是如何有这么多upvotes?这不会返回任何** ** – Guy 2014-03-07 12:57:59

1

计算是这样的:

x = 1 - 1/3 + 1/5 - 1/7 + 1/9 (... etc as far as possible.) 
PI = x * 4 

你已经得到了皮!

这是我所知道的最简单的方法。

PI的值慢慢收敛到Pi的实际值(3.141592165 ......)。如果迭代次数越多越好。

20

有关使用方法:

double pi = Math.PI; 

如果你想比这更好的精度,则需要使用一个算法系统和Decimal类型。

+3

我认为这是一个罕见的情况,当你需要有比你更精确的来自Math.PI; – 2010-02-12 23:12:25

0

在任何生产场景中,我都会强迫您查看值,达到所需的小数点数,并将其作为'const'存储在您的类可以到达的某个位置。

(除非你正在写的科学 '皮' 特定的软件......)

4

不同的算法很好的概述:

我不确定第一个链接中的Gauss-Legendre-Salamin算法的复杂性(我会说O(N log^2(N)log(log(N))))) 。

我确实鼓励你去尝试一下,不过,收敛速度真的是很快。

此外,我不确定为什么试图将一个非常简单的过程算法转换为递归算法?请注意,如果您对性能感兴趣,那么以有界精度工作(通常需要“双精度”,“浮点”,...输出)并不是真的有意义,因为这样的明显答案情况就是硬编码的价值。

-8
public double PI = 22.0/7.0; 
0

关于...

...如何去了解它从学习的角度来看。

您是否正在学习编程科学方法?或生产生产软件?我希望社区认为这是一个有效的问题,而不是挑剔。

在这两种情况下,我认为写你自己的Pi是一个解决的问题。德米特里已经显示'Math.PI'常数。在同一空间内攻击另一个问题!去寻找通用的牛顿近似值或者光滑的东西。

1

这是一个很好的方法(从the main Wikipedia entry on pi);它比上面讨论的简单公式更快地收敛,并且如果您的意图是将递归作为学习练习,那么它就非常适合递归解决方案。 (假设你在学习经验之后,我没有给出任何实际的代码。)

基本公式与上面相同,但是此方法对部分和进行平均以加速收敛。

定义两个参数的函数,馅饼(H,W),使得:

pie(0,1) = 4/1 
pie(0,2) = 4/1 - 4/3 
pie(0,3) = 4/1 - 4/3 + 4/5 
pie(0,4) = 4/1 - 4/3 + 4/5 - 4/7 
... and so on 

所以你率先探索递归机会是代码,“水平”计算的“宽度”参数增大(对于“零”的高度)。

然后用这个公式添加第二维度:

pie(h, w) = (pie(h-1,w) + pie(h-1,w+1))/2 

其中使用,当然,只为h的大于零的值。

该算法的好处在于,您可以轻松地用电子表格嘲笑它,以便在您探索逐渐变大的参数所产生的结果时检查代码。在你计算饼图的时候(10,10),对于大多数工程目的来说,你将拥有一个pi的近似值。

2

什么是PI?圆的周长除以其直径。

在计算机图形学中,您可以绘制/绘制一个圆,其中心位于0,0处,从初始点x,y开始,可以使用一个简单的公式找到下一个点x',y': x'= x + y/h:y'= y - x'/ h

h通常是2的幂,因此可以很容易地通过移位(或从双指数中减去)来完成划分。 h也想成为你的圈子的半径r。一个简单的起始点是x = r,y = 0,然后计算c的步数直到x < = 0绘制一个四舍五入的圆。 PI是4 * c/r或PI是4 * c/h

递归到任何深度,通常对于商业程序是不切实际的,但尾递归允许算法以递归方式表达,而实现为循环。递归搜索算法有时可以使用队列而不是进程的堆栈来实现,搜索必须从一个deadend中回溯并采取另一种路径 - 这些回溯点可以放在一个队列中,多个进程可以对这些点进行排队并尝试其他路径。

6

有一些真正的,真正的老花样,我很惊讶,没有看到这里。

atan(1)== PI/4,所以当一个可信的反正切函数 存在的旧栗子是4 * atan(1)。

一个非常可爱的固定比率的估计,使旧的西方22/7看起来像污垢 是355/113,这是很好的小数点后的位置(至少三或四,我认为)。 在某些情况下,对于整数算术,这甚至足够好:乘以355然后除以113.

355/113也很容易承诺记​​忆(对于某些人来说):count one,one,three,三,五,五,并记住你在分母和分子中的数字(如果你忘记了哪一个三联体位于顶端,一微秒的思想通常会把它解决掉)。

请注意,22/7给你:3.14285714,千分之一是错误的。

355/113给你3.14159292直到十万分之一没有错。

Acc。到/usr/include/math.h在我的盒子上,M_PI被定义为: 3.14159265358979323846 这可能是很好的。

从估算PI中得到的教训是有很多方法可以做到这一点, 没有一个是完美的,你必须按照预期用途进行排序。

355/113是中国古老的估计,我相信它预计在22/7前多年。当我还是一名本科生时,这是由一位物理学教授教给我的。

0

@Thomas Kammeyer:

注意ATAN(1.0)是经常硬编码,所以4 * ATAN(1.0)是不是一个真正的 '算法' 如果你调用一个库ATAN函数(一个相当很少有人已经建议通过用一系列(或无限产品)代替Atan(x),然后在x = 1处进行评估。

另外,很少有情况下,您需要更多pi精度高于几十位(可以很容易地进行硬编码!)我研究过数学应用,计算一些(非常复杂的)数学对象(它是具有整数系数的多项式),I必须对真实和复数(包括计算pi)进行算术运算,其精度高达几百万位......但这在现实生活中并不常见:)

您可以查找以下内容示例code

1
Enumerable.Range(0, 100000000).Aggregate(0d, (tot, next) => tot += Math.Pow(-1d, next)/(2*next + 1)*4) 
6

如果你仔细看这个真的很好的指导:

Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4

你会发现在第70页这个可爱的实现(从我身边微小的变化):

static decimal ParallelPartitionerPi(int steps) 
{ 
    decimal sum = 0.0; 
    decimal step = 1.0/(decimal)steps; 
    object obj = new object(); 

    Parallel.ForEach(
     Partitioner.Create(0, steps), 
     () => 0.0, 
     (range, state, partial) => 
     { 
      for (int i = range.Item1; i < range.Item2; i++) 
      { 
       decimal x = (i - 0.5) * step; 
       partial += 4.0/(1.0 + x * x); 
      } 

      return partial; 
     }, 
     partial => { lock (obj) sum += partial; }); 

    return step * sum; 
} 
0

我喜欢this paper,它解释了如何基于反正切的泰勒级数展开来计算π。

纸开始与简单假设

ATAN(1)=π/ 4弧度

ATAN(X)可以与泰勒级数

被迭代地估计

atan(x)= x - x^3/3 + x^5/5 - x^7/7 + x^9/9 ...

该论文指出了为什么这不是特别有效,并继续对该技术进行一些逻辑改进。他们还提供了一个计算π到几千位的示例程序,并附有源代码,包括所需的无限精度数学例程。

1
using System; 

namespace Strings 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

/*   decimal pie = 1; 
      decimal e = -1; 
*/ 
      var stopwatch = new System.Diagnostics.Stopwatch(); 
      stopwatch.Start(); //added this nice stopwatch start routine 

    //leibniz formula in C# - code written completely by Todd Mandell 2014 
/* 
      for (decimal f = (e += 2); f < 1000001; f++) 
      { 
       e += 2; 
       pie -= 1/e; 
       e += 2; 
       pie += 1/e; 
       Console.WriteLine(pie * 4); 
      } 

       decimal finalDisplayString = (pie * 4); 
       Console.WriteLine("pie = {0}", finalDisplayString); 
       Console.WriteLine("Accuracy resulting from approximately {0} steps", e/4); 
*/ 

// Nilakantha formula - code written completely by Todd Mandell 2014 
// π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) - (4/(12*13*14) etc 

      decimal pie = 0; 
      decimal a = 2; 
      decimal b = 3; 
      decimal c = 4; 
      decimal e = 1; 

      for (decimal f = (e += 1); f < 100000; f++) 
      // Increase f where "f < 100000" to increase number of steps 
      { 

       pie += 4/(a * b * c); 

       a += 2; 
       b += 2; 
       c += 2; 

       pie -= 4/(a * b * c); 

       a += 2; 
       b += 2; 
       c += 2; 

       e += 1; 
      } 

      decimal finalDisplayString = (pie + 3); 
      Console.WriteLine("pie = {0}", finalDisplayString); 
      Console.WriteLine("Accuracy resulting from {0} steps", e); 

      stopwatch.Stop(); 
      TimeSpan ts = stopwatch.Elapsed; 
      Console.WriteLine("Calc Time {0}", ts); 

      Console.ReadLine(); 

     } 
    } 
} 
1
public static string PiNumberFinder(int digitNumber) 
    { 
     string piNumber = "3,"; 
     int dividedBy = 11080585; 
     int divisor = 78256779; 
     int result; 

     for (int i = 0; i < digitNumber; i++) 
     { 
      if (dividedBy < divisor) 
       dividedBy *= 10; 

      result = dividedBy/divisor; 

      string resultString = result.ToString(); 
      piNumber += resultString; 

      dividedBy = dividedBy - divisor * result; 
     } 

     return piNumber; 
    } 
0

首先,请注意C#可以使用.NET框架的Math.PI领域:

https://msdn.microsoft.com/en-us/library/system.math.pi(v=vs.110).aspx

这里的很好的功能是,它是一个完整的精密两倍您可以使用或与计算结果进行比较。该URL中的选项卡对于C++,F#和Visual Basic具有相似的常量。

要计算更多地方,您可以编写自己的扩展精度代码。一个是快速编码和相当快,易于程序是:

PI = 4 * [4 *反正切(1/5) - 反正切(239分之1)]

此公式和许多其他包括一些会聚于惊人的快率,每次术语如50位数字,处于钨:

Wolfram Pi Formulas