2010-11-05 222 views
5

我正在寫一個函數來計算PI的值,並將其作爲雙精度值返回。到現在爲止還挺好。但是,一旦函數在小數點後達到14位數,它就不能再保留了。我假設這是因爲雙精度有限。我應該怎麼做才能在小數點後繼續獲得更多數字?C#高雙精度

回答

16

我不會在浮點完成它。

回想一下,你的算法是:

(1 + 1/(2 * 1 + 1)) * 
(1 + 2/(2 * 2 + 1)) * 
(1 + 3/(2 * 3 + 1)) * 
(1 + 4/(2 * 4 + 1)) * 
(1 + 5/(2 * 5 + 1)) * 
(1 + 6/(2 * 6 + 1)) * 
(1 + 7/(2 * 7 + 1)) * ... 

沿着您計算分數的方式每個階段。爲什麼不簡單地將分數保持在分子/分母形式?要計算的分數是:

(4/3) * 
(7/5) * 
(10/7) * 
(13/9) * ... 

這僅僅是4 * 7 * 10 * 13 ...上底部的頂部和3 * 5 * 7 * 9。

獲得一個BigInteger類(其中一個隨System.Numerics中的4.0框架提供),您可以輕鬆計算出分子和分母的大小。那麼你只是將商數轉換爲十進制的問題。那很容易。據推測你知道如何做長分區。只需在分子和分母上實施一個長分割算法,即可得出所需數量的數字。

8

你需要多少精度?

使用decimal會給你大約28位小數:

decimal pi = 3.14159265358979323846264338327950288419716939937510m; 
Console.WriteLine(pi); // 3.1415926535897932384626433833 

如果這還不夠你,那麼你就需要尋找某種BigDecimal的實現,或者看看其他技術進行計算。

0

是的,這是因爲雙精度有限。有很多不同的方法來計算pi的數字。我會建議問你最喜歡的搜索引擎,「如何計算pi的數字」。

0

您可以使用J#BigDecimal類型,如this answer中所建議的那樣。

1

有幾個庫可以讓您以任意精度工作。一個是W3b.sine,但在wikipedia上描述了其他幾個。

1

嘗試decimal而不是雙倍。它不能存儲大到雙倍的數字,但我認爲小數點後的精度更高。如果你需要更多,你可能不得不使用一個字符串。

+0

我不會使用字符串 - 你會有額外的開銷轉換爲/從數字。 – JLWarlow 2010-11-05 15:13:30

+0

是的,但是如果你需要比呃更高的28位精度,那麼就沒有內置的數據類型。 IIRC C#確實有一些類的值(幾乎)無限大小,我很確定它會將它們作爲字符串內部存儲... – user472875 2010-11-05 15:20:24

+0

...或一個字節數組。 – 2010-11-05 16:01:54