什么编程语言支持任意精度算术?

时间:2008-09-27 03:07:57

标签: programming-languages bigdecimal arbitrary-precision

哪些编程语言支持任意精度算术,你能举一个如何打印任意数字的简短例子吗?

18 个答案:

答案 0 :(得分:14)

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

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

this article的“任意精度软件”部分为您提供了很好的选择。

答案 1 :(得分:11)

的Mathematica。

N[Pi, 100]

3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068

mathematica不仅具有任意精度,而且默认情况下它具有无限精度。它保留1/3作为有理数,甚至包含像Sqrt [2]这样的东西的表达式,它保持符号,直到你要求数字近似,你可以有任意数量的小数位。

答案 2 :(得分:6)

在Common Lisp中,

(format t "~D~%" (expt 7 77))
printf格式的“~D~%”将是“%d \ n”。 Common Lisp中内置了任意精度算法。

答案 3 :(得分:6)

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

答案 4 :(得分:5)

Python具有这样的能力。有一个很好的例子here

来自文章:

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的说明。

答案 5 :(得分:5)

很多人推荐使用Python的十进制模块,但我建议使用mpmath而不是十进制来进行任何严格的数字用途。

答案 6 :(得分:3)

Scheme(lisp的变体)具有称为“bignum”的功能。有许多好的方案实现可用于完整语言环境和可嵌入脚本选项。 我可以担保的一些

MitScheme(也称为gnu计划) PLTScheme Chezscheme Guile(也是一个gnu项目) 方案48

答案 7 :(得分:3)

<强> COBOL

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

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

<强> PL / 1

DCL VALUE DEC FIXED (4,4);

:-)我记不起其他旧东西......

开玩笑,正如我的例子所示,我认为你不应该选择一种编程语言,具体取决于一个功能。实际上所有体面的和最近的语言支持一些专用类中的固定精度。

答案 8 :(得分:3)

Ruby整数和浮点数(在数学上说:有理数)默认情况下并不严格依赖于经典的CPU相关限制。在Ruby中,如果大小超过经典大小的最大值,整数和浮点数将自动,透明地切换为某些“bignum类型”。

有人可能想要使用一些使用“bignums”的合理优化和“完整”,多种多样的数学库。这就是类似Mathematica的软件真正发挥其功能的地方。

截至2011年,Mathematica非常昂贵,并且非常受限于黑客攻击和转发的观点,特别是,如果想要将数学软件作为小型,低价格端,Web应用程序或开源项目的组件运送。如果只需要进行原始数字运算,而不需要可视化,那么Mathematica和Maple就有了一个非常可行的替代方案。另一种选择是REDUCE计算机代数系统,它基于Lisp,开源和成熟(几十年)并在积极开发(2011年)。与Mathematica一样,REDUCE使用符号计算。

为了识别Mathematica我说,截至2011年,在我看来,Mathematica在交互式可视化方面是最好的,但我认为从编程的角度来看,即使Mathematica是开源的,也有更方便的选择。项目。对我来说,似乎Mahtematica也有点慢,不适合处理庞大的数据集。在我看来,Mathematica的利基是理论数学,而不是现实生活中的数字运算。另一方面,Mathematica的出版商Wolfram Research正在托管和维护地球上最高质量,最高质量,免费使用的数学参考站点之一:http://mathworld.wolfram.com/ 与Mathematica捆绑在一起的在线文档系统也非常好。

在谈论速度时,值得一提的是REDUCE据说甚至可以在Linux路由器上运行。 REDUCE本身是用Lisp编写的,但它带有2个自己特定的Lisp实现。其中一个Lisps是用Java实现的,另一个是用C实现的。至少从数学的角度来看,它们都能很好地工作。 REDUCE有两种模式:传统的“数学模式”和“程序员模式”,允许通过REDUCE自编写的语言完全访问所有内部:Lisp。

所以,我的观点是,如果看一下编写数学例程所需的工作量,更不用说所有在REDUCE中都是MATURE的符号计算,那么可以节省大量的时间(几十年,确切地说,通过在REDUCE中完成大部分数学部分,特别是它已经由专业数学家在很长一段时间内进行了测试和调试,用于对旧时代的超级计算机进行符号计算以实现真正的专业任务并且工作得非常好在现代低端计算机上真正快速。它不会在我身上崩溃,不像至少一个我不想在这里命名的商业包装。

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

为了说明,在实践中符号计算是必不可少的,我举了一个通过矩阵求逆求解线性方程组的例子。要反转矩阵,需要找到决定因素。使用直接CPU支持的浮点类型进行的舍入可以将理论上具有逆的矩阵渲染到不具有逆的矩阵。这又引入了一种情况,大多数情况下软件可以正常工作,但如果数据有点“不幸”,那么应用程序崩溃,尽管事实上算法上软件没有任何问题,除了舍入浮点数。

绝对精确有理数确实存在严重的局限性。使用它们执行的计算越多,它们消耗的内存就越多。截至2011年,我不知道该问题的任何解决方案,除了小心并跟踪已经使用数字执行的操作的数量,然后舍入数字以节省内存,但是必须在一个非常精确的计算阶段,以避免上述问题。如果可能的话,那么应该在计算的最后进行舍入作为最后一次操作。

答案 9 :(得分:3)

在PHP中你有BCMath。您不需要加载任何DLL或编译任何模块。 支持任何大小和精度的数字,表示为字符串

<?php

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

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

?>

答案 10 :(得分:2)

显然Tcl也有它们,从版本8.5开始,由LibTomMath提供:

http://wiki.tcl.tk/5193
http://www.tcl.tk/cgi-bin/tct/tip/237.html
http://math.libtomcrypt.com/

答案 11 :(得分:2)

在R中,您可以使用Rmpfr包:

library(Rmpfr)
exp(mpfr(1, 120))
## 1 'mpfr' number of precision  120   bits 
## [1] 2.7182818284590452353602874713526624979

您可以在此处找到小插图:Arbitrarily Accurate Computation with R: The Rmpfr Package

答案 12 :(得分:2)

有几个Javascript库可以处理任意精度算术 例如,使用我的big.js库:

Big.DP = 20;                      // Decimal Places
var pi = Big(355).div(113)    

console.log( pi.toString() );    // '3.14159292035398230088'

答案 13 :(得分:1)

Java本身可以使用BigDecimal进行bignum操作。 GMP是使用C / C ++的bignum的事实标准库。

答案 14 :(得分:1)

如果您想在.NET世界中工作,您仍然可以使用java.math.BigDecimal类。只需添加对vjslib的引用(在框架中),然后就可以使用java类了。

最棒的是,它们可以在任何.NET语言中使用。例如在C#中:

    using java.math;

    namespace MyNamespace
    {
        class Program
        {
            static void Main(string[] args)
            {
                BigDecimal bd = new BigDecimal("12345678901234567890.1234567890123456789");

                Console.WriteLine(bd.ToString());
            }
        }
    }

答案 15 :(得分:1)

(免费的)基本程序x11 basic(http://x11-basic.sourceforge.net/)对于整数具有任意精度。 (以及一些有用的命令,例如nextprime(abcd ... pqrs))

答案 16 :(得分:1)

IBM 的解释性脚本语言 Rexx,通过 Numeric 提供自定义精度设置。 https://www.ibm.com/docs/en/zos/2.1.0?topic=instructions-numeric。 该语言在大型机和 PC 操作系统上运行,具有非常强大的解析和变量处理以及扩展包。 Object Rexx 是最新的实现。来自 https://en.wikipedia.org/wiki/Rexx

的链接

答案 17 :(得分:0)

Haskell 对内置的任意精度算术有很好的支持,使用它是默认行为。在 REPL 中,无需导入或设置:

Prelude> 2 ^ 2 ^ 12
1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190336

(在 https://tryhaskell.org/ 上亲自尝试)

如果您正在编写存储在文件中的代码,并且想要打印一个数字,则必须先将其转换为字符串。 show 函数就是这样做的。

module Test where

main = do
  let x = 2 ^ 2 ^ 12
  let xStr = show x
  putStrLn xStr

(在 code.world 上自己尝试:https://www.code.world/haskell#Pb_gPCQuqY7r77v1IHH_vWg

此外,Haskell 的 Num 抽象使您可以尽可能推迟决定使用哪种类型。

-- Define a function to make big numbers.  The (inferred) type is generic.
Prelude> superbig n = 2 ^ 2 ^ n

-- We can call this function with different concrete types and get different results.
Prelude> superbig 5 :: Int
4294967296
Prelude> superbig 5 :: Float
4.2949673e9

-- The `Int` type is not arbitrary precision, and we might overflow.
Prelude> superbig 6 :: Int
0

-- `Double` can hold bigger numbers.
Prelude> superbig 6 :: Double
1.8446744073709552e19
Prelude> superbig 9 :: Double
1.3407807929942597e154

-- But it is also not arbitrary precision, and can still overflow.
Prelude> superbig 10 :: Double
Infinity

-- The Integer type is arbitrary-precision though, and can go as big as we have memory for and patience to wait for the result.
Prelude> superbig 12 :: Integer
1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190336

-- If we don't specify a type, Haskell will infer one with arbitrary precision.
Prelude> superbig 12
1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190336