Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯凯尔山脉和浮标_Haskell_Floating Point_Range Notation - Fatal编程技术网

Haskell 哈斯凯尔山脉和浮标

Haskell 哈斯凯尔山脉和浮标,haskell,floating-point,range-notation,Haskell,Floating Point,Range Notation,为什么浮点数的Haskell范围表示法的行为与整数和字符的不同 Prelude> [1, 3 .. 10] :: [Int] [1,3,5,7,9] Prelude> [1, 3 .. 10] :: [Float] [1.0,3.0,5.0,7.0,9.0,11.0] Prelude> ['a', 'c' .. 'f'] "ace" 如果最后一个元素接近上限,我可以理解,但这显然不是舍入问题。语法[e1,e2..e3]实际上是enumfromthen到e1 e2 e3的语法

为什么浮点数的Haskell范围表示法的行为与整数和字符的不同

Prelude> [1, 3 .. 10] :: [Int]
[1,3,5,7,9] 
Prelude> [1, 3 .. 10] :: [Float]
[1.0,3.0,5.0,7.0,9.0,11.0]
Prelude> ['a', 'c' .. 'f']
"ace"

如果最后一个元素接近上限,我可以理解,但这显然不是舍入问题。

语法
[e1,e2..e3]
实际上是
enumfromthen到e1 e2 e3
的语法糖,这是
Enum
类型类中的一个函数

定义其语义如下:

对于类型
Int
Integer
,枚举函数具有 以下含义:

  • 来自e1的序列
    enumfrome1
    是列表
    [e1,e1+1,e1+2,…]
  • 序列
    enumFromThen e1 e2
    是列表
    [e1,e1+i,e1+2i,…]
    , 其中,
    i
    的增量为
    e2− e1
    。增量可以是零或零 消极的如果增量为零,则所有列表元素都是 一样
  • 序列
    enumFromTo e1 e3
    是列表
    [e1,e1+1,e1+2,…e3]
    。 如果
    e1>e3
    ,则列表为空
  • 序列
    enumFromthen到e1 e2 e3
    是列表
    [e1,e1+i,e1+
    2i,…e3]
    ,其中增量
    i
    ,为
    e2− e1
    。如果增量为 如果为正或为零,则列表将在下一个元素为时终止 大于
    e3
    ;如果
    e1>e3
    ,则列表为空。如果增量为 否,当下一个元素小于
    e3
    ;如果
    e1
    ,则列表为空
这与您期望的差不多,但是
Float
Double
实例的定义不同:

对于
Float
Double
,上述
Int
规则给出了
enumFrom
族的语义,但当元素大于
e3+i时列表终止∕2
用于正增量
i
,或当它们小于
e3+i时∕2
用于负片
i

我不确定这是什么理由,所以我能给你的唯一答案是,它是这样的,因为它在标准中是这样定义的

您可以通过使用整数枚举并随后转换为
Float
来解决此问题

Prelude> map fromIntegral [1, 3 .. 10] :: [Float]
[1.0,3.0,5.0,7.0,9.0]

好吧,@Henning Makholm在评论中已经说过了,但他没有解释为什么这实际上是一个更好的解决方案

首先要说的是:在处理浮点时,我们必须始终注意可能的舍入错误。当我们写
[0.0,0.1..1.0]
时,我们必须意识到,除第一个数字外,所有这些数字都不会精确到十分之一的位置。在我们需要这种确定性的地方,我们根本不能使用浮动

当然,在许多应用程序中,我们满足于合理的确定性,但需要高速。那是浮动的好地方。此类列表的一种可能应用是简单的梯形数值积分:

trIntegrate f l r s = sum [ f x | x<-[l,(l+s)..r] ] * s - (f(l)+f(r))*s/2
然后我们得到

bad_trIntegrate ( \x -> exp(x + cos(sqrt(x) - x*x)) ) 1.0 3.0 0.1
=>21.27550564546988


这与隐藏浮点问题无关。这只是一种帮助程序员更容易解决这些问题的方法。事实上,
[1,3..10]:Float的反直觉结果有助于记住这些问题

可能是想让
[0.0,0.1..1.0]
这样的东西或多或少像一个人天真地期望不知道浮点不精确一样工作。@Henning:我想如果人们假设在常见的用例中,
e3
的顺序是
[e1,e1+I..]
,这是有道理的,忽略错误。在OP的例子中,
e3
介于两个值之间,这在某种意义上是该假设的最坏情况。我进一步主张,任何不知道浮点不精确性问题的人都不应该使用浮点值。一般来说,在性能不是主要问题的地方使用任意精度理性,并学习如何正确使用浮动。这是Haskell规范中的一个讨厌的错误。它试图隐藏浮点固有的问题,但这只意味着问题会在其他地方出现。@LeftAround关于我知道浮点是如何工作的,试图解决问题只会给我带来更多的问题。我希望
enumFromThenTo
继续添加增量,并尽可能长地使用元素,但为什么为有理数指定相同的行为?这里没有不精确之处。@André这确实有点不可思议。行为是与整数不兼容还是与浮点不兼容是一个选择。依我看,理性与浮动的关系更为密切,因此将它们放在该框中而不是积分框中是合理的在分数区间(与整数区间相反)中,始终可以选择区间大小为整数倍的步长。在这种情况下,
Rational
s的范围和
Float
s的范围的行为就像一个人直觉预期的那样,因此我们应该简单地确保这个条件总是满足的。经过思考,我同意区间大小。如果这个条件没有满足,IRC上甚至有人认为这是一个错误。起初我认为这很可笑,但现在我明白他的意思了。我同意在很多情况下,这简化了生活。然而,它引入了新的问题:
sum[dx*sqrt(1-x)|x@undur_;或者,如果省略最后一项,这样的总和通常也会给出错误的结果;只有在特殊情况下,如
sqrt(1-1)
这不要紧。我要再次指出,明显错误的NaN比听起来合理但顺序不准确的浮点数更糟糕。-要真正确定像这样的东西,使用可能与
bad_trIntegrate ( \x -> exp(x + cos(sqrt(x) - x*x)) ) 1.0 3.0 0.1