我有一个关于Haskell floor
函数的问题 - 它应该返回“不大于参数的最大整数”但表达式
floor 3.9999999999999999
返回4而不是3.它可能与Double
类型精度有关,但是考虑到Haskell类型安全的重要性它不应该编译,无论如何在这种情况下它返回的数字大于参数这与其定义相矛盾。
答案 0 :(得分:22)
在这种情况下,它返回的数字大于与其定义相矛盾的参数。
它返回一个等于其参数的数字。如你所说,这是双精度。数字3.9999999999999999和4在64位浮点规则下相互简单。
但是考虑到Haskell类型安全的重要性,它不应该编译
问题是像这样的分数文字具有多态类型Fractional a => a
。那就是他们不必是双打。例如,您可以编写floor (3.9999999999999999 :: Rational)
,它将正确返回3,因为3.9999999999999999可以表示为Rational
而不会有任何精度损失。
如果Haskell写错了3.9999999999999999
,那么你也将无法编写3.9999999999999999 :: Rational
,这会很糟糕。因此,由于Fractional
字面值可以使用许多不同的类型来表示,其中一些类型具有无限的精度,因此Haskell基于{{1}限制合法Fractional
文字的数量将是一个很大的错误。的限制。
有人可能会争辩说,Haskell在用作Double
时应限制3.9999999999999999
,但在使用Double
时则不会。但是,这需要Rational
类型类的实例来声明有关其精度的信息(以便Haskell可以使用该信息来确定给定的文字是否对该类型有效),它目前不具备哪个,哪个将是难以(或不可能)以一般,有效和用户友好的方式实施(考虑到术语“精确度”可能意味着完全不同的事情取决于我们是在谈论浮点数还是定点数以及它们是否使用base 2或10(或其他任何东西)来表示数字 - 对于Fractional
类型类的实例,其中任何一个都是可能的。
答案 1 :(得分:9)
这与类型安全无关。例如,检查http://babbage.cs.qc.cuny.edu/IEEE-754/上的值。如果长度短或等于64位,则3.9999999999999999
和4
的值对于浮点数完全相同。你得到的价值并不大 - 它完全一样。
如果您需要如此高的精确度,请查看http://www.haskell.org/haskellwiki/Libraries_and_tools/Mathematics#Arbitrary_precision