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

Posted

技术标签:

【中文标题】什么是最好的(便携式)跨平台任意精度数学库? [关闭]【英文标题】:What are the best (portable) cross-platform arbitrary-precision math libraries? [closed] 【发布时间】:2010-04-02 18:36:40 【问题描述】:

我正在寻找一个好的 C 或 C++ 任意精度数学库。你能给我一些意见或建议吗?

主要要求:

    必须处理任意大的整数——我的主要兴趣是整数。如果你不知道任意大这个词是什么意思,想象一下像 100000 这样的数字! (100000的阶乘)。

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

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

    必须有效地处理加法(+)、减法(-)、乘法(*)、整数除法(/)、余数(%),幂 (**)、递增 (++)、递减 (--)、GCD、阶乘和其他常见整数算术计算。处理不产生整数结果的函数(如平方根和对数)的能力是一个加分项。处理symbolic computations的能力更胜一筹。

这是我目前发现的:

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

    bcPythonRubyHaskell、LispErlangOCamlPHP、其他一些语言:我用过其中的一些,但我不知道他们使用的是哪个库,或者他们使用的是哪种实现。

我已经知道的:

    char 用于十进制数字,char* 用于十进制字符串,并使用for-loop 对数字进行计算。

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

    使用整数类型将十进制数字(或几位数字)存储为BCD (Binary-coded decimal)。

    Booth’s multiplication algorithm.

我不知道的:

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

我的欣赏:

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

    关于我应该阅读的书籍和文章的好建议。例如,用数字说明non-naive二进制到十进制转换算法的工作原理会很好。 Douglas W. Jones 的文章“Binary to Decimal Conversion in Limited Precision”就是一篇好文章的例子。

    任何一般的帮助。

如果您认为使用double(或long double,或long long double)可以轻松解决此问题,请不要回答此问题。如果您确实这么认为,那么您就没有理解所讨论的问题。

【问题讨论】:

在我看来,GMP 似乎是一个不错的库。我想知道为什么 Python / Haskell / Erlang / 等的贡献者需要重新发明***。如果GMP那么好,为什么不依赖它呢? GPL / LGPL 许可证可能是问题之一,但尽管如此(以及舍入模式问题),GMP 还有其他缺点吗? Python / Haskell / Erlang / 任何密码库的内置整数是否比 GMP 更快?如果是这样,如果许可允许,我想提取并使用它。 我在cs.uiowa.edu/~jones/bcd/decimal.html 找到了 Douglas W. Jones 的一篇不错的文章。本文介绍了一种仅使用 8 位整数算术将 16 位整数转换为十进制表示的方法。这个想法是将 16 位数字分成 4 个半字节,每个半字节代表一个以 16 为基数的“数字”。所以,digit-0 (n0) 代表 x1,n1 => x16,n2 => x256,n3 => x4096。那么,很明显十进制数(d0)的digit-0是n0 * 1 + n1 * 6 + n2 * 6 + n3 * 6的结果的digit-0。通过正确处理进位,d1到d4可以也可以计算。 然而,据我所知,Douglas 的上述想法无法扩展到处理任意长的二进制整数。这是因为数字 1 (16^0)、16 (16^1)、256 (16^2) 和 4096 (16^3) 是预先计算好的。那么问题就变成了如何用十进制表示任意大的 n 的 16^n。 【参考方案1】:

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

您要求提供相关的书籍或文章。 bignums 的棘手部分是长除法。我推荐 Per Brinch Hansen 的论文 Multiple-Length Division Revisited: A Tour of the Minefield。

【讨论】:

感谢您提供论文链接!是的,我同意除法是最棘手的部分。我很久以前就知道如何使用“纸笔法”手工除法:-),因此可以将相同的方法应用于char * 的十进制字符串(每个char 代表一个十进制数字)或 BCD 字符串的 int *(每个 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* 3* 4)的试错乘法,或者在循环中进行连续减法。你看它有多慢?我相信存在更高效的算法。 @Sui:Brinch Hanson 展示了如何将试错法减少到最多两次试验。这真的很令人印象深刻。 好的,让我更详细地看一下论文。谢谢! 我不确定您最终在哪里找到了解决方案,也不确定您使用什么格式来存储数字,但是 COBOL 的 COMP-3 nybble 格式更好处理,因为它更紧凑,每 4 位存储一个 0-9 值,并且,您不需要从 ASCII 字符值中减去十六进制 30 以获得可用数字。【参考方案2】:

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

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

【讨论】:

感谢您的回复!您提到了“代码可移植性”。你能解释一下问题是什么吗?我认为 GMP 是可移植的,并且在主要平台上都受支持... “代码可移植性”与“主要平台支持”不同。 Python 使用一个简单的实现,它对 C 编译器的行为做很少的假设,因此相同的代码几乎可以在任何 C 编译器上编译。 GMP 使用更多的代码(C 和高度调整的程序集),使 GMP 更快,但也对 C 编译器和汇编器的行为做出更多假设。例如,Microsoft Visual Studio 编译器不能很好地支持 GMP。有一个名为 MPIR (www.mpir.org) 的 GMP 分支,它确实支持 Microsoft 的编译器。 我明白了。这意味着 Python 实现更像 ANSI C,而 GMP 实现使用 __asm 技巧……谢谢您的解释。【参考方案3】:

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

【讨论】:

嘿!这是一个易于使用的库,它似乎利用了 CPU 的能力,并使用了一些 C++ 模板魔法来完成这项工作。很棒的图书馆!为你 +1! 是的,它有一个许可的非 copyleft BSD 许可证。 来自上面的页面:“可以在编译时设置多大的值。” - 所以这不符合要求。【参考方案4】:

我自己并没有将任意精度的算术库相互比较,但确实有人似乎或多或少一致地选择了 GMP。值得一提的是,GHC Haskell 和 GNU Guile Scheme 中的任意精度整数都是使用 GMP 实现的,而pidigits benchmark on the language shootout 的最快实现是基于 GMP。

【讨论】:

谢谢! ^___^ 不错的信息!【参考方案5】:

Pari 呢?它建立在*** GMP 之上,并提供了您将需要的所有其他关于数论运算的好东西(以及许多符号计算的东西)。

【讨论】:

嗨 fortran(!),它看起来不错!感谢您的信息! 不客气 :-) 此外,使用 Pari,您可以使用 GP 推出快速原型,并且当您高兴时编写优化的 C 版本(我认为它带有 GP->C 编译器来帮助也有)

以上是关于什么是最好的(便携式)跨平台任意精度数学库? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

PHP BC 数学 函数

Java千百问_09基础类库(003)_java.math包有什么功能

用于任意数字精度的 .NET Framework 库

用于高级综合的任意精度浮点库

C/C++ 中最好的加密库是啥? [关闭]

VS 2015 中的类库 - 构建跨平台库