2010-11-05 232 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