Haskell floor函数返回不同的结果

6 haskell

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

floor 3.9999999999999999

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

sep*_*p2k 22

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

它返回一个等于其参数的数字.如你所说,这是双精度.在64位浮点规则下,数字3.9999999999999999和4简单地相互相等.

但鉴于Haskell类型安全的重要性,它不应该编译

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

如果Haskell写错了3.9999999999999999,那么你也无法写3.9999999999999999 :: Rational,哪个不好.因此,由于Fractional文字可以使用许多不同的类型来表示,其中一些类型具有无限的精度,因此Haskell基于限制限制法律Fractional文字的数量将是一个很大的错误Double.

有人可能会争辩说,Haskell 3.9999999999999999在用作a时会受到限制Double,但在使用a时则不会Rational.但是,这将需要Fractional类型类的实例来声明有关其精度的信息(以便Haskell可以使用该信息来确定给定的文字是否对该类型有效),它当前没有,哪个难以(或不可能)以一般,有效和用户友好的方式实施(考虑到术语"精确度"可能意味着完全不同的事情取决于我们是在谈论浮点数还是定点数以及它们是否使用2或10基数(或其他任何东西)来表示数字 - 其中任何一种都可以用于Fractional类型类的实例).


vir*_*tor 9

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

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

  • 要求'Double`文字可以准确表示将有点烦人.当你想要`0.1`时,你必须写`0.1000000000000000055511151231257827021181583404541015625`. (4认同)
  • @ sepp2k:如果您希望这是一个编译错误,您应该知道会产生什么影响.例如,`0.1`不能用Double(或任何二进制浮点格式iirc)准确表示.但是使`(0.1 :: Double)`编译错误将是不切实际的. (2认同)