6

我有一个关于 Haskellfloor函数的问题 - 它应该返回“不大于参数的最大整数”但是表达式

floor 3.9999999999999999

返回 4 而不是 3。它可能与Double类型精度有关,但考虑到 Haskell 类型安全的重要性,它不应该编译,无论如何在这种情况下它返回的数字大于与其定义相矛盾的参数。

4

2 回答 2

22

在这种情况下,它返回大于与其定义相矛盾的参数的数字。

它返回一个等于其参数的数字。正如你所说,这是关于双精度。在 64 位浮点规则下,数字 3.9999999999999999 和 4 完全相等。

但是考虑到 Haskell 类型安全的重要性,它不应该编译

问题是像这样的分数文字具有多态类型Fractional a => a。那就是他们不必是双打。例如,您可以编写floor (3.9999999999999999 :: Rational)3,因为 3.9999999999999999 可以表示为 aRational而不会损失任何精度。

如果 Haskell 写错了3.9999999999999999,那么你也不能写3.9999999999999999 :: Rational,这很糟糕。因此,由于Fractional可以使用许多不同的类型来表示文字,其中一些具有无限精度,因此 HaskellFractional根据Double' 的限制来限制合法文字的数量将是一个大错误。

有人可能会争辩说,Haskell3.9999999999999999在用作 a 时应该限制Double,而不是在用作 a 时Rational。但是,这将需要Fractional类型类的实例来声明有关其精度的信息(以便 Haskell 可以使用该信息来确定给定的文字是否对该类型有效),而这目前还没有,这将是困难的(或不可能的)以通用、高效和用户友好的方式实现(考虑到“精度”一词的含义可能完全不同,具体取决于我们谈论的是浮点数还是定点数,以及它们是使用基数 2 还是 10 (或其他任何东西)来表示数字 - 对于Fractional类型类的实例,其中任何一个都是可能的)。

于 2013-04-23T10:26:09.543 回答
9

这与类型安全无关。例如,检查http://babbage.cs.qc.cuny.edu/IEEE-754/上的值。3.9999999999999999如果长度小于或等于 64 位,则和的值4对于浮点数完全相同。你得到的价值并不大——它是完全一样的。

如果您需要如此高的精度,请查看http://www.haskell.org/haskellwiki/Libraries_and_tools/Mathematics#Arbitrary_precision

于 2013-04-23T10:26:21.233 回答