Haskell floor函数返回不同的结果

Haskell floor函数返回不同的结果,haskell,Haskell,关于Haskellfloor函数,我有一个问题-它应该返回“不大于参数的最大整数”,但返回表达式 楼层3.9999999999999 返回4而不是3。它可能与Double类型精度有关,但鉴于Haskell类型安全的重要性,它不应该编译,无论如何,在这种情况下,它返回的数字大于与其定义相矛盾的参数 在本例中,它返回的数字大于与其定义相矛盾的参数 它返回一个与其参数相等的数字。正如你所说,这是关于双精度的。在64位浮点规则下,数字3.9999999999999和4只是彼此相等 但是考虑到Haskel

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

楼层3.9999999999999

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

在本例中,它返回的数字大于与其定义相矛盾的参数

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

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

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

如果Haskell在编写
3.9999999999999999
时出错,那么您也将无法编写
3.9999999999999::Rational
,这将很糟糕。因此,由于一个
分数
文本可以使用许多不同的类型来表示,其中一些类型具有无限的精度,因此Haskell基于
双重
的限制来限制合法
分数
文本的数量将是一个巨大的错误


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

这与类型安全无关。例如,检查上的值。如果长度小于或等于64位,则浮点数的
3.9999999999999
4
的值完全相同。你得到的值并没有变大——完全一样


如果您需要如此高的精度,请查看

无论您的浮点数格式有多少位,它都是有限的,并且将舍入无法精确表示的常量。当
3.99999999999999999
转换为double时,甚至在
floor
看到它之前,
3.99999999999999
似乎被舍入为
4.0
。我想问题是,如果用户试图编写一个
double
而实际上不能正确表示为
double
并且编译器允许,那么这是一种类型错误,编译器没有捕捉到。@sepp2k:如果您希望这是一个编译错误,您应该知道这会有什么影响<例如,code>0.1
,不能用双精度(或任何二进制浮点格式iirc)精确表示。但是使
(0.1::Double)
产生编译错误是不切实际的。@tauli我不想要任何东西,我是在解释OP的观点。我还认为,在这种情况下,我们可以定义“一个可以准确表示为双精度的文字”来表示“一个字符串表示将与文字等效的数字”,这将导致一些有用的规则,关于哪些文本可以被接受,哪些不可以。要求
Double
文本可以精确表示会有点烦人。当您想要
0.1
时,您必须编写
0.10000000000000005551151231257827021181583404541015625