哪些编程语言支持任意精度算术,你能举一个简短的例子来说明如何打印任意数量的数字吗?
18 回答
有些语言内置了这种支持。例如,看看Java中的java.math.BigDecimal或 Python 中的decimal.Decimal。
其他语言通常有一个库可提供此功能。例如,在 C 中,您可以使用GMP或其他选项。
本文的“任意精度软件”部分很好地概述了您的选择。
数学。
N[Pi, 100]
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
mathematica 不仅具有任意精度,而且默认情况下它具有无限精度。它将诸如 1/3 之类的东西保留为有理数,甚至包含诸如 Sqrt[2] 之类的表达式,它象征性地维护,直到您要求一个数字近似值,您可以拥有任意数量的小数位。
在 Common Lisp 中,
(format t "~D~%" (expt 7 77))
printf 格式的“~D~%”将是“%d\n”。任意精度算术内置于 Common Lisp 中。
Smalltalk 从一开始就支持任意精度的整数和分数。请注意,gnu Smalltalk 实现确实在后台使用了 GMP。我还在为各种方言(Squeak/Pharo Visualworks 和 Dolphin)开发 ArbitraryPrecisionFloat,请参阅http://www.squeaksource.com/ArbitraryPrecisionFl.html
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 的说明。
许多人推荐 Python 的 decimal 模块,但我建议在任何严重的数字用途中使用mpmath over decimal。
COBOL
77 VALUE PIC S9(4)V9(4).
一个带符号的变量,有 4 位小数。
PL/1
DCL VALUE DEC FIXED (4,4);
:-) 我不记得其他旧的东西了...
开个玩笑,正如我的示例所示,我认为您不应该根据单个功能选择编程语言。几乎所有体面的和最近的语言都支持某些专用类中的固定精度。
在 PHP 中你有 BCMath。您不需要加载任何 dll 或编译任何模块。支持任意大小和精度的数字,以字符串表示
<?php
$a = '1.234';
$b = '5';
echo bcadd($a, $b); // 6
echo bcadd($a, $b, 4); // 6.2340
?>
Scheme(lisp 的一种变体)具有称为“bignum”的功能。有许多好的方案实现可用,包括完整的语言环境和可嵌入的脚本选项。一些我可以保证的
MitScheme(也称为gnu scheme)PLTScheme Chezscheme Guile(也是gnu项目)Scheme 48
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 有 2 种模式:传统的“数学模式”和“程序员模式”,它允许通过自己编写的 REDUCE 语言完全访问所有内部结构:Lisp。
所以,我的观点是,如果看一下编写数学例程所需的工作量,更不用说在 REDUCE 中都成熟的所有符号计算,那么可以节省大量时间(几十年,字面意思)通过在REDUCE中完成大部分数学部分,特别是考虑到它已经过长时间的专业数学家的测试和调试,用于在旧时代的超级计算机上进行符号计算以完成真正的专业任务,并且工作得非常好,真的很快,在现代低端计算机上。它也没有在我身上崩溃,与至少一个我不想在这里命名的商业包不同。
http://www.reduce-algebra.com/
为了说明,符号计算在实践中是必不可少的,我举了一个通过矩阵求逆求解线性方程组的例子。要反转矩阵,需要找到行列式。使用 CPU 直接支持的浮点类型进行的舍入可以将理论上具有逆矩阵的矩阵渲染为没有逆矩阵的矩阵。这反过来又引入了一种情况,在大多数情况下,软件可能工作得很好,但如果数据有点“不幸”,那么应用程序就会崩溃,尽管在算法上除了四舍五入之外软件没有任何问题浮点数。
绝对精度有理数确实有一个严重的限制。使用它们执行的计算越多,它们消耗的内存就越多。截至 2011 年,我不知道该问题的任何解决方案,除了小心并跟踪使用数字执行的操作数量,然后将数字四舍五入以节省内存,但必须在一个非常精确的计算阶段,以避免上述问题。如果可能,则应在计算的最后作为最后一次操作进行舍入。
有几个 Javascript 库可以处理任意精度的算术。
例如,使用我的big.js库:
Big.DP = 20; // Decimal Places
var pi = Big(355).div(113)
console.log( pi.toString() ); // '3.14159292035398230088'
显然 Tcl 也有它们,从 8.5 版开始,由 LibTomMath 提供:
http://wiki.tcl.tk/5193 http://www.tcl.tk/cgi-bin/tct/tip/237.html http://math.libtomcrypt.com/
在 R 中,您可以使用Rmpfr包:
library(Rmpfr)
exp(mpfr(1, 120))
## 1 'mpfr' number of precision 120 bits
## [1] 2.7182818284590452353602874713526624979
您可以在此处找到小插图:使用 R 进行任意准确计算:Rmpfr 包
Java 本机可以使用 BigDecimal 进行 bignum 操作。GMP是使用 C/C++ 的 bignum 的事实上的标准库。
如果您想在 .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());
}
}
}
(免费)基本程序 x11 basic(http://x11-basic.sourceforge.net/)对整数具有任意精度。(还有一些有用的命令,例如 nextprime(abcd...pqrs))
IBM 的解释性脚本语言 Rexx 提供了带有数字的自定义精度设置。 https://www.ibm.com/docs/en/zos/2.1.0?topic=instructions-numeric。该语言在大型机和 pc 操作系统上运行,并具有非常强大的解析和变量处理以及扩展包。Object Rexx 是最新的实现。来自https://en.wikipedia.org/wiki/Rexx的链接
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