Java浮点高精度库

23

有哪些Java库可以提供具有数千位精度的浮点或定点运算快速实现?它们的性能如何?

我需要的一个要求是,它实现了比朴素的乘法算法更好的乘法算法,对于比原来大2倍的数字,需要的时间只有朴素算法的四分之一(请参阅乘法算法)。


从兴趣的角度来看,一个普遍的问题是:您的应用程序需要几千位小数精度? - Simon
1
这是一项爱好,而非工作:我想要计算更多位 http://en.wikipedia.org/wiki/Feigenbaum_constant 的数值。 - Hans-Peter Störr
4个回答

40
任意精度算术页面上提到了三个库:java.math(包含BigDecimal),ApfloatJScience。我对它们进行了一些速度测试,只使用加法和乘法。
结果是,对于相对较小的数字,BigDecimal可以接受(1000位数字的速度是其他库的一半),但如果您使用更多的数字,它就大大落后了——JScience大约快4倍。但明显的性能优胜者是Apfloat。其他库似乎使用天真的乘法算法,其时间与数字位数的平方成正比,但Apfloat的时间似乎几乎呈线性增长。在10000位数字上,它比JScience快4倍,但在40000位数字上,它比JScience快16倍。
另一方面:JScience为数学问题提供了优秀的功能:矩阵、向量、符号算法、解方程组等。所以我可能会选择JScience,并稍后编写一个包装器将Apfloat集成到JScience算法中——由于良好的设计,这似乎很容易实现。
(更新:我为JScience的数字包编写了一个测试套件,并修复了许多错误。这已经包含在版本4.3.1中。所以我建议去试试。)

2
一些库是否支持三角函数? - user502187
你是说一旦超过某个位数阈值,JScience就能保持大约4倍的速度优势吗?还是速度差异会随着位数的增加而更加明显? - Asad Saeeduddin
@Asad 我没有做过这样详细的实验,但我猜测它们使用不同的算法和不同的时间复杂度。(至少对于乘法等运算而言。)因此,速度差异会随着位数的增加而变得越来越大。但是,如果你想要更多的位数,你需要进行自己的实验,也许还有更好的库可以使用。 - Hans-Peter Störr

7

你是否检查过BigDecimal的性能?在JavaDoc中我没有看到明显的东西,但这肯定是我的首选。


1
对于非常高的精度,这会慢得多。我只建议在您只有几十个数字或不关心速度时使用。 - Hans-Peter Störr
@hstoerr:很好,你已经检查过了 - 但我认为“测试最简单的可行方案”的方法(内置是一个重要的起点优势)仍然是一个很好的初始步骤 :) - Jon Skeet
BigDecimal相对有限,例如与JScience相比,它不支持sqrt。 - Tomasz

3
你可以查看JScience库以及他们的Real数字类。我不确定相对于BigDecimal性能如何,但该库的目标是为科学应用提供高度调整的类,这似乎是一个好迹象。

-3

Apfloat提供了尾数的高精度,但指数的精度似乎比通常的要低(基于这样一个事实:对于double可以处理的值,它会崩溃并显示“零的对数”)。因此,它对大数没有用处。

此外,文档中还说:

“使用构造函数Apfloat(float,long)和Apfloat(double,long)存在一个陷阱。由于浮点数和双精度数在内部总是以基数2表示,将其转换为任何其他基数通常会导致舍入误差,并且得到的apfloat不会准确地达到所需的位数。

例如,0.3无法在基数2中准确表示。当您像new Apfloat(0.3f, 1000)这样构造一个apfloat时,得到的数字不会准确地达到1000位,而只能大约达到7位(在基数10中)。实际上,得到的数字将是类似于0.30000001192092896...的东西。”

这使得Apfloat似乎最小限度有用。

BigDecimal没有对数函数,并且文档也没有说明它是否允许您制作比double更大的数字;指数是32位的,有点像。


1
实际上,Phil,这个陷阱的原因是因为你正在使用浮点数或双精度数构造Apfloat。不准确是因为你传递了一个不准确的数字。如果你花时间阅读下一段,你会发现如果你用字符串构造它,你可以拥有无限的精度。 - Snickers
BigDecimal 0.3 将是准确的。以此为例。Apfloat 是否有从 BigDecimal 构造函数?BigDecimal 在表示上有点混合,尾数是基于 2 的(BigInteger),但指数是基于 10 的。 - user502187

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接