2008-09-02 37 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