最好的(便携式)跨平台任意精度数学库是什么?[关闭]


81

我正在寻找一个使用C或C ++编写的良好的任意精度数学库。您能给我一些建议吗?

主要要求:

  1. 必须处理任意大的整数-我的主要兴趣是整数。如果您不知道任意大这个词的含义,请想象一下类似100000的东西!(阶乘为100000)。

  2. 在库初始化或对象创建期间,不必指定精度。精度应受系统可用资源的限制。

  3. 利用平台的全部功能,并应本地处理“小”数字。这意味着在64位平台上,计算(2 ^ 33 + 2 ^ 32)应该使用可用的64位CPU指令。该库不应以与在同一平台上使用(2 ^ 66 + 2 ^ 65)相同的方式来计算该值。

  4. 必须有效地处理加(+),减(-),乘(*),整数除(/),余数(%),幂(**),增量(++),减(--),GCD,阶乘和其他常见的整数算术计算。能够处理不会产生整数结果的函数(例如平方根和对数)是一个加号。处理符号计算的能力甚至更好。

这是我到目前为止发现的内容:

  1. JavaBigIntegerBigDecimal类:到目前为止,我一直在使用它们。我已经阅读了源代码,但是我不理解下面的数学原理。它可能基于我从未学过的理论和算法。

  2. 内置整数类型或bcPythonRubyHaskellLispErlangOCamlPHP以及其他一些语言的核心库:我使用了其中一些,但不知道它们使用的是哪个库,或者他们正在使用哪种实现。

我已经知道的:

  1. 使用char十进制数字和char*十进制字符串,做用数字计算for-loop。

  2. 使用int(或long intlong long)作为基本的“单位”,并使用该类型的数组作为任意长整数,并使用for-loop对元素进行计算。

  3. 使用整数类型将十进制数字(或几位数)存储为BCD(二进制编码的十进制)

  4. 布斯的乘法算法

我不知道的是:

  1. 不使用天真的方法,将上述二进制数组以十进制打印。天真的方法的一个示例:(1)从最低到最高的位相加:char*1、2、4、8、16、32 ,……(2)使用上面提到的-string来存储中间十进制结果)。

我的赞赏:

  1. GMPMPFRdecNumber(或您认为不错的其他库)上进行了很好的比较。

  2. 关于我应该阅读的书籍和文章的好的建议。例如,用数字说明非原始的二进制到十进制转换算法是如何工作的将是很好的。道格拉斯·W·琼斯(Douglas W. Jones)的文章“有限精度的二进制到十进制转换”是一个很好的例子。

  3. 任何帮助一般。

如果您认为使用(或或)可以轻松解决此问题,请不要回答此问题。如果您这样认为,则您将不理解所涉及的问题。doublelong doublelong long double


3
据我所知,GMP似乎是一个很好的库。我想知道的是为什么需要Python / Haskell / Erlang / etc的贡献者来重新发明轮子。如果GMP这么好,为什么不依赖它呢?GPL / LGPL许可证可能是其中的一个问题,但是尽管有这个问题(还有四舍五入模式的问题),GMP还有其他缺点吗?Python / Haskell / Erlang /任何加密库的内置整数是否比GMP快?如果是这样,如果许可的话,我想提取并使用它。
小清庞-明日香贤治

我在Douglas W. Jones的cs.uiowa.edu/~jones/bcd/decimal.html上找到了一篇不错的文章。本文介绍了一种仅使用8位整数算术将16位整数转换为十进制表示形式的方法。这个想法是将16位数字分成4个半字节,每个半字节代表一个以16为底的“数字”。因此,数字0(n0)代表x1,n1 => x16,n2 => x256,n3 => x4096。然后,很明显十进制数(d0)的数字0是n0 * 1 + n1 * 6 + n2 * 6 + n3 * 6的结果的数字0。通过正确处理进位,d1到d4可以也可以计算。
小清庞-明日香贤治

但是,据我所料,道格拉斯的上述想法不能扩展为处理任意长的二进制整数。这是因为数字1(16 ^ 0),16(16 ^ 1),256(16 ^ 2)和4096(16 ^ 3)是预先计算的。然后,问题就变成了如何对任意大的n用十进制表示16 ^ n。
小清庞-明日香贤治

Answers:


24

GMP是流行的选择。Squeak Smalltalk有一个非常不错的库,但是它是用Smalltalk编写的。

您要求提供相关的书籍或文章。bignums的棘手部分是长除法。我推荐Per Brinch Hansen的论文《再探多学科:雷区之旅》


感谢您链接到本文!是的,我同意分裂是最棘手的部分。我很早以前就知道如何使用“纸和铅笔方法”进行手工除法:-),因此可以将相同的方法应用于十进制字符串char *(每个char代表十进制数字)或int *BCD字符串(每个int代表4/8/16个BCD数字)。但是,我想知道现实世界中的生产级库是否模仿“纸笔方法”,因为它太慢了。
小清庞-明日香贤治

要知道为什么,让我们想象一下它是如何运行的100,000,000,000,000,000 / 333,333,333,333:第一步是比较100,000,000,000333,333,333,333。由于前者少于后者,因此计算仅移至下一位。第二步是找到的商1,000,000,000,000 / 333,333,333,333,这涉及333,333,333,333 * 1(和* 2* 3* 4)的反复试验乘法,或者在循环中进行连续减法。你看到它有多慢吗?我相信存在更有效的算法。
小清庞-明日香贤治

3
@Sui:Brinch Hanson展示了如何将反复试验方法减少到最多两次试验。真的非常令人印象深刻。
诺曼·拉姆齐

好吧,让我对本文进行更详细的了解。谢谢!
小清庞-明日香贤治

1
我不确定您最终在哪里找到解决方案,也不确定用于存储数字的格式,但是COBOL的COMP-3 nybble格式要好得多,因为它更紧凑,每4位存储一个0-9值AND,则不需要从ASCII字符值中减去十六进制30即可得到可用的数字。

13

总的来说,他最快的通用任意精度库是GMP。如果要使用浮点值,请查看MPFR库。MPFR基于GMP。

关于其他语言的本机任意精度支持,由于许可证,代码大小和代码可移植性的原因,Python使用其自己的实现。该GMPY模块让Python的访问GMP库。


感谢您的答复!您提到了“代码可移植性”。您能解释一下是什么问题吗?我认为GMP具有可移植性,并且在主要平台上都受支持...
小清庞-明日香研二

2
“代码可移植性”与“在主要平台上支持”不同。Python使用一种简单的实现,该实现很少对C编译器的行为做出任何假设,因此相同的代码几乎可以在任何C编译器上进行编译。GMP使用更多的代码(C和经过高度优化的汇编),这些代码可使GMP更快,但也对C编译器和汇编器的行为进行了更多假设。例如,Microsoft Visual Studio编译器不能很好地支持GMP。有一个名为MPIR(www.mpir.org)的GMP分支,它确实支持Microsoft的编译器。
casevh 2010年

我懂了。这意味着Python实现更像ANSI C,而GMP实现使用__asm技巧...谢谢您的解释。
小清庞-明日香贤治

8

请参阅TTMath,这是一个小型的模板化的仅标头的库,免费供个人和商业使用。


嘿! 这是一个易于使用的库,似乎它利用了CPU功能,并且使用了一些C ++模板魔术来完成这项工作。很棒的图书馆!为您+1!
小清庞-明日香贤治

是的,它有一个许可的非copyleft BSD许可证。
–plasmcel

在上一页中:“可以在编译时设置多个值。” -因此不符合要求。
osxdirk


4

Pari呢?它建立在顶级GMP之上,并提供了所有您需要的数论运算的所有其他优点(以及许多符号计算的内容)。


嗨,fortran(!),看起来不错!感谢您的信息!
小清庞-明日香贤治

不客气:-)另外,您也可以使用Pari使用GP快速滚动原型,并在满意的情况下编写优化的C版本(我认为它也随GP-> C编译器一起提供帮助)
fortran
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.