哪些编程语言支持任意精度浮点数?

6
这个问题要求列举编程语言,这些语言可以接受数字常量用于赋值给任意精度变量或者在任意精度表达式中使用,而无需在赋值或应用之前将其转换为IEEE浮点表示。例如,以下伪代码的赋值表达式:
BigNum x = 0.1;

许多编程语言提供或可以访问库,从文本字符串构建类似于BigNum类型的对象。我正在寻找能够直接将数值标记(如0.1)转换为BigNum的编程语言,而不需要程序员创建必须解析并可能在运行时引发异常或标志错误的字符串。相反,我对编译器或分词器可以在将数字文字处理成任意精度十进制或整数比例表示之前,报告格式不正确的数字或无效表达式的语法错误感兴趣。
根据Rosetta Code网站上关于Literals/Floating point的描述,看起来JMapleMaxima提供了任意精度浮点数的文字语法。是否还有其他更广泛使用的编程语言提供类似于我上面提供的伪代码的功能?

以一个具体的例子来说,Julia 提供了内置的支持有理数的功能。这些数字具有可以在源代码中使用的文字表示。例如:

x = 1//10

现在,在十进制中,1//100.1是相同的数。然而,大多数编程语言会将源代码中的文字十进制数转换为IEEE浮点数。通常这正是所需的。然而,许多不熟悉IEEE浮点数表示法或已经淡出历史的类似浮点数表示法的人会惊讶地发现,当它被转换为二进制小数时,十分之一并不完全等于十分之一。此外,当浮点“错误”积累而平均/抵消时,这种惊奇通常会在“大多数时间”工作的代码产生令人惊讶的结果后出现。当然,这就是浮点表示和算术操作的本质,它们在实践中非常有用。请注意:计算机科学家应该了解的浮点算术知识
我发现有时整数不够用,而浮点数会在本来精确的计算中引入不必要的问题。为此,有理数和任意精度库很适合解决这个问题。很好。然而,我仍然想知道是否有任何语言支持在语言本身中直接表示有理数和任意精度字面量。毕竟,我不想使用只有字符串文字的语言,这些文字必须在运行时被解析为数字。

到目前为止,Julia是有理数的一个很好的答案,但远非唯一支持有理数文字的语言。然而,它没有任意精度文字。对于这个问题,J、Maple和Maxima似乎都有我所寻找的东西。也许这几乎是完整的列表了。但是,如果有人知道另外一个或两个候选者,我会感激他们的指导...

目前的答案...

到目前为止最好的答案是Haskell。它提供了丰富的对数字类型和操作的理解,以及包括有理数表达式的数字文字表示法,似乎在所有情况下都可以将带有小数部分的十进制数视为有理数而不是浮点文字。至少,这是我从快速阅读Haskell文档和一个我偶然发现的博客文章Overloading Haskell numbers, part 3, Fixed Precision中得出的结论,在该文章中,作者指出:

……注意到看起来像浮点文字实际上是有理数,这是原始Haskell设计中非常聪明的决定之一。

对于许多程序员来说,Julia更易接近,并提供对各种数学类型和操作的出色支持,以及通常出色的性能。然而,Python 也具有非常出色的语法,许多原生编译的包与今天可用于Julia的那些相匹配或超越,并且无疑在商业、开源和学术项目中享有更广泛的采用和应用 - 尽管,如果我有选择的话,我的个人偏好是Julia。
对于我自己,我将花更多时间研究Haskell,并重新审视Ocaml/F#,这可能是介于Julia/Python之类的语言和像Haskell这样的语言之间的可行选择 - 这些编程语言如何在某种谱系上分布留给读者作为练习。如果Ocaml/F#在我感兴趣的情况下提供了与Haskell相当的表达能力,则基于当前和可能的未来采用率,它们可能是更好的选择。但就目前而言,Haskell似乎是我最初问题的最佳答案。

这对你为什么很重要? - Marcin
我编写的大部分软件都涉及数学计算,几乎完全由基本算术运算组成。用户输入的每个数字以及我的代码中使用的每个文字或用于单元测试的文字都代表一个整数或有限数字的比率(即有理数)。然而,即使对于给定的输入,用户提供的非常简单的数字也不能被表示为IEEE浮点数。例如,用户必须输入一组分数,这些分数在给定模型下总和为1.0(例如,.8、.1、.1)。 - Ned
1
因为这涉及到处理用户输入,所以你不需要一种使用字面语法来处理它的语言。无论如何,你都需要解析输入,因此可以使用任何语言中的库来驱动它。关注其他需求来选择语言(包括构建必要解析器的易用性)。 - Marcin
当然,我可以对每个用例进行编码,但这可能会很繁琐。我正在寻找候选语言以在未来项目中使用 - 或当前项目的新版本 - 其中算术运算可以有效地支持有理数的操作,包括以小数表示的分数。在很大程度上,Julia 符合我的要求,尽管它不是唯一合理的选择。 - Ned
然而,Julia没有一种简洁的表示十进制数的符号,编译器应该将其转换为有理数或任意精度的十进制数。与Java和许多其他语言不同,例如0.1这样的数字必须手动分解为1//10,或者作为字符串传递给一个函数,该函数使用另一个小解析器构造正确类型的数字对象,而编译器则对字符串的内容或语义一无所知。 - Ned
显示剩余12条评论
3个回答

3

Haskell 拥有由任意精度整数支持的有理数,还有重载的数字字面量,因此大多数情况下,您的字面量具有所需的类型。


1
在当前可用的编程语言中,Haskell最直接地提供了我所要求的内容。它也是我调查或被推荐的任何替代方案中使用和撰写最广泛的语言,尽管与最广泛使用的语言相比,甚至Haskell的流行程度也非常有限。与Julia等语言相比,它的语法和语义对于那些不熟悉数学符号和概念的程序员来说更加令人望而生畏。无论如何,这就是我正在寻找的答案。谢谢。 - Ned

2
在Smalltalk中,Visualworks扩展了st-80语法以引入1.23s,它是FixedPoint的一个实例(并不是一个好名字...),在内部表示为有理数分数123/100。
这个数字的行为就像一个分数,可以有任意长的分子和分母,并执行精确算术,只是它有一些特定的打印规则:它会四舍五入到小数点后的固定位数。1.23s4四舍五入到4位小数->'1.2300',1.23s按提供的小数位数进行四舍五入,因此是2。
在Visualworks之后,大多数Smalltalk方言添加了一些等效的类和相同的文字语法。在Squeak中,该类被命名为ScaledDecimal,但只有1.23s2语法被实现在编译器中。Pharo将在3.0版本中也包括1.23s。

0
在Scheme中,有两种类型的数字,精确和非精确,这种区别与数字类型(整数、有理数、实数、复数)是正交的。对非精确数字进行操作会产生非精确结果,而非精确数字通常被实现为IEEE浮点数。为了方便起见,带有小数点或指数的数字文字被认为是非精确的,没有小数点或指数的数字文字被认为是精确的,因此1和1/10和1+2i是精确的,而1.0和0.1和1.0+2.0i是非精确的。但是,您可以通过在文字前加上#e使其成为精确的或#i使其成为非精确的来覆盖此设置,因此#e3.0与3相同,#e0.1与1/10相同,#i1/10与0.1相同。

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