【问题标题】:Haskell floor function returns different resultsHaskell floor 函数返回不同的结果
【发布时间】:2013-05-10 20:01:00
【问题描述】:

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

floor 3.9999999999999999

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

【问题讨论】:

  • 无论您的浮点数格式有多少位,它都是有限的,并且会舍入无法准确表示的常量。似乎3.9999999999999999 甚至在floor 看到它之前就被舍入到4.0。

标签: haskell


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    如果你需要这么高的精度,看看http://www.haskell.org/haskellwiki/Libraries_and_tools/Mathematics#Arbitrary_precision

    【讨论】:

    • 我认为关键在于,如果用户尝试编写实际上无法正确表示为 Double 的 Double 并且编译器允许这样做,那么这是一种类型错误编译器没有捕捉到。
    • @sepp2k:如果您希望这是一个编译错误,您应该知道这会产生什么影响。例如,0.1 不能用 Double(或任何二进制浮点格式 iirc)准确表示。但是让(0.1 :: Double) 编译错误是不切实际的。
    • @tauli 我什么都不想要,我在解释(我对)OP 的观点。另外我认为在这种情况下,我们可以将“可以准确表示为 Double 的文字”定义为“其字符串表示形式将等同于文字的数字”,这将导致一些有用的规则来确定哪些文字将被接受哪个不会。
    • 要求 Double 字面量可以精确表示会有点烦人。当你想要0.1 时,你必须写0.1000000000000000055511151231257827021181583404541015625。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 2011-12-27
    • 2021-12-01
    • 1970-01-01
    • 2012-12-27
    • 2020-07-04
    相关资源
    最近更新 更多