Clojure中默认的十进制字面量为什么不是BigDecimal类型?

9
我了解到Clojure读取器将带有后缀“M”的十进制文字面量(如1.23M)解释为BigDecimal类型。我也知道没有“M”的十进制数变成Java的double类型。
但我认为更好的方法是让普通的十进制数成为BigDecimal类型,而依赖主机的小数则添加后缀,例如1.23H。这样,当数字因IEEE double的精度限制而被损坏或截断时,我们可以轻松注意到数字的精度受限。此外,我认为更易于表达的方式应该是独立于主机的。

除了时间性能之外,Clojure将字面十进制解释为Java double类型是否有其他原因?我不认为时间性能是一个答案,因为它不是C/C++,声明依赖于主机的十进制数的其他方法可以像“1.23H”一样实现。
2个回答

11
曾经,对于整数,Clojure 会在需要时自动提升到更大的尺寸。但现在已改为引发溢出异常。我从远处感觉到:
  1. 支配者希望 Clojure 是一种实用语言,在合理的时间内完成实际工作。他们不希望因数字操作意外使用任意精度库而导致性能下降。相比之下,Scheme似乎更注重数学美感而非实用性。
  2. 人们不喜欢在运行时被惊讶地发现互操作调用失败,因为Java库期望32位整数而不是任意大小的整数。
所以决定使用普通整数(我认为是Java长整数)作为默认值,并且仅在程序员有意识地决定愿意承受性能损失和互操作损失时才使用任意大整数。
我猜测类似的决策也适用于带有小数点的数字。

5

性能可能是一个问题。也许 clojure.core 开发者可以就此发表看法。

我个人认为,默认情况下没有 bigdecimal 也不是什么大问题,因为:

  • 正如你所指出的,有一个字面量:M
  • 有一些操作,例如+'*'-'...(注意引号),它们“支持任意精度”。

我注意到Clojure在使用*运算符时会自动将long类型升级为BigInt。然而,当我键入(*' 1e200 1e200)(*' 1e-200 1e-200)时,REPL只会输出Infinity0.0。为什么这些自动升级函数不支持double类型呢? - burrownn
1
虽然我来晚了,但是问题在于1e200是一个浮点数常量而不是整数。如果你想要进行这个乘法运算,你可以通过将浮点数值转换为BigInt来实现:(*' (bigint 1e200) (bigint 1e200)),这将产生1(400个零)N - Bob Jarvis - Слава Україні

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