哪些编程语言支持任意精度算术?

23

哪些编程语言支持任意精度算术,并且你能给出一个简短的例子来打印任意数量的数字吗?

18个回答

14

一些语言内置了这种支持。例如,看看 Java 中的 java.math.BigDecimal,或者 Python 中的 decimal.Decimal

其他语言通常有可用的库来提供此功能。例如,在 C 语言中,您可以使用 GMP 或其他选项。

这篇文章 的“任意精度软件”部分提供了一个很好的选择概述。


8
Java对任意精度算术的支持相当差,正是因为它不是语言的一部分。好吧,BigDecimal是标准库的一部分,但它不是语言的一部分。您不能使用普通算术运算符与BigDecimal一起使用。 - Dan Dyer
1
正如@DanDyer所说。问题明确要求支持任意精度算术的语言,而Java不支持。BigDecimal是某人使用该语言实现自己的任意精度算术类/库。但我怀疑几乎任何非平凡的语言都会有这样的库可用。这不是问题所问的。 - aroth

13

Mathematica.

->

Mathematica。

N[Pi, 100]

3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068

Mathematica不仅具有任意精度,而且默认情况下它具有无限精度。它将像1/3这样的东西保持为有理数,甚至涉及Sqrt [2]之类的表达式,它会在你要求进行数字近似之前维护符号性,你可以将其近似到任意小数位数。


6

Smalltalk从一开始就支持任意精度整数和分数。 需要注意的是gnu Smalltalk实现在底层使用了GMP。 我也正在为各种方言(Squeak/Pharo Visualworks和Dolphin)开发ArbitraryPrecisionFloat,请参见http://www.squeaksource.com/ArbitraryPrecisionFl.html


6
在Common Lisp中,
(format t "~D~%" (expt 7 77))

在printf格式中,"~D~%"将被翻译为"%d\n"。Common Lisp内置了任意精度算术。

有没有办法打印出1/3的小数点后n位? - Matt Gregory
如果您打印(/ 1 3)的值,它将是"1/3"或类似的内容。在可用内存的限制范围内,您可以使用精确的整数和有理数进行计算。小数点属于浮点数,并且通常Lisp系统将使用标准浮点数。 - David Thornley

6
Python具备这种能力。这里有一个很好的例子(点击此处)
从文章中可以看到:
from math import log as _flog
from decimal import getcontext, Decimal

def log(x):
    if x < 0:
        return Decimal("NaN")
    if x == 0:
        return Decimal("-inf")
    getcontext().prec += 3
    eps = Decimal("10")**(-getcontext().prec+2)
    # A good initial estimate is needed
    r = Decimal(repr(_flog(float(x))))
    while 1:
        r2 = r - 1 + x/exp(r)
        if abs(r2-r) < eps:
            break
        else:
            r = r2
    getcontext().prec -= 3
    return +r

此外,Python快速入门教程讨论了任意精度:http://docs.python.org/lib/decimal-tutorial.html,并描述了getcontext:
getcontext()函数访问当前上下文并允许更改设置。 编辑:添加有关getcontext的说明。

那个链接已经失效了,你发布的代码也无法运行。getcontext()是什么? - Matt Gregory
在我的回答中添加了澄清。 - torial

5
许多人推荐使用Python的decimal模块,但我建议在任何严肃的数字运算中使用mpmath代替decimal。

正如其名称所示,Decimal旨在使用十进制(基数10)数字,这对于某些目的(财务计算等)非常相关,但对于算术目的而言并不是很高效。其他模块对基于二进制的数字块执行算术运算。当速度成为问题时,mpmath和gmpy非常高效。 - Thomas Baruchel

4

COBOL

77 VALUE PIC S9(4)V9(4). 

一个带有4位小数的有符号变量。

PL/1

DCL VALUE DEC FIXED (4,4);

:-) 我记不得其他旧的东西了...

开玩笑的,正如我的例子所示,我认为你不应该仅根据单一功能选择编程语言。几乎所有好的和最新的编程语言都支持在一些专门的类中支持固定精度。


如果你只是想用这种语言完成一个任务,那么你应该这样做。 - Matt Gregory
@Oli,然而,原帖的要求是任意精度(arbitrary precision),而你的两个示例都没有展示出来。 - bugmagnet

3
Ruby的整数和浮点数(在数学上称为有理数)默认情况下并不严格绑定于经典CPU相关的限制。如果大小超过了经典大小的最大值,则Ruby的整数和浮点数会自动、透明地切换到某些“bignum类型”。人们可能希望使用一些合理优化和“完整”的多方面数学库,该库使用“bignums”。这就是类似Mathematica软件真正发挥其功能的地方。
截至2011年,Mathematica非常昂贵,并且从黑客和重新分销的角度来看非常受限制,特别是如果一个人想将数学软件作为小型、低价格端的Web应用程序或开源项目的组件进行分发。如果只需要进行原始数字计算,而不需要可视化,则存在一个非常可行的替代Mathematica和Maple的选择。这个选择是REDUCE计算机代数系统,它基于Lisp,是开源且成熟的(几十年来一直如此),并正在积极开发(2011年)。与Mathematica一样,REDUCE使用符号计算。
对于Mathematica的认识,我认为从2011年开始,它似乎是交互式可视化方面最好的,但我认为从编程角度来看,即使Mathematica是一个开源项目,也有更方便的替代品。在我看来,Mathematica也有点慢,不适合处理大型数据集。在我看来,Mathematica的领域是理论数学,而不是实际的数字计算。另一方面,Mathematica的出版商Wolfram Research维护着地球上最高质量(如果不是最高质量)的免费数学参考网站之一:http://mathworld.wolfram.com/。与Mathematica捆绑在一起的在线文档系统也非常好。
谈到速度,值得一提的是REDUCE被称为可在Linux路由器上运行。REDUCE本身是用Lisp编写的,但它带有两种非常特定的Lisp实现。其中一个Lisp是用Java实现的,另一个是用C实现的。两者都可以很好地工作,至少从数学角度来看。REDUCE有两种模式:传统的“数学模式”和“程序员模式”,允许使用REDUCE自己编写的语言Lisp完全访问所有内部功能。

因此,我的观点是,如果考虑编写数学例程所需的工作量,更不用说所有符号计算都已成熟,那么通过在REDUCE中完成大部分数学部分,可以节省大量时间(几十年),特别是考虑到它已经被专业数学家测试和调试了长时间,用于在旧时代超级计算机上进行符号计算以完成真正的专业任务,并且在现代低端计算机上运行得非常快。与至少一个商业软件包不同,它从未崩溃过,我不想在这里透露其名称。

http://www.reduce-algebra.com/

为了举例说明,在实践中,符号计算是必不可少的。我举一个通过矩阵求逆解决线性方程组的例子。要求一个矩阵的逆矩阵,需要找到行列式。直接由 CPU 支持的浮点类型所进行的四舍五入可能会将一个在理论上有逆矩阵的矩阵变成没有逆矩阵的矩阵。这反过来会引入一种情况,即大多数时候软件可能运行得很好,但如果数据有点“不幸”,那么应用程序就会崩溃,尽管从算法上讲,软件没有任何问题,除了浮点数的舍入之外。
绝对精度有理数确实存在一个严重的限制。进行更多的计算会消耗更多的内存。截至2011年,我不知道除了小心谨慎并跟踪已执行的操作数量并将数字舍入以节省内存之外,还有其他解决该问题的方法,但必须在计算的非常精确的阶段进行舍入,以避免上述问题。如果可能,舍入应该在计算的最后一步完成。

3

Scheme(一种Lisp的变体)具有称为“bignum”的功能。现在有许多优秀的Scheme实现,包括完整的语言环境和可嵌入的脚本选项。

以下是我可以保证的几个实现:

  • MitScheme(也称为GNU Scheme)
  • PLTScheme
  • Chezscheme
  • Guile(也是GNU项目)
  • Scheme 48

3

在PHP中,你可以使用BCMath。你不需要加载任何dll文件或编译任何模块。该函数支持任意大小和精度的数字,以字符串形式表示。

<?php

$a = '1.234';
$b = '5';

echo bcadd($a, $b);     // 6
echo bcadd($a, $b, 4);  // 6.2340

?>

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