在Haskell中`foldl`和`fol​​dr`的数值问题

我有以下Haskell脚本来计算函数f(x) = (2- x) - (2^3 - x^3/12)

calc x = (x - (x ^ 3) / 12)
calc2 x = (calc 2) - (calc x)

calcList1 :: [Float] -> Float
calcList1 l = foldl (+) 0.0 (map calc2 l)

calcList2 :: [Float] -> Float
calcList2 l = foldr (+) 0.0 (map calc2 l)

test1 :: Float -> Float
test1 step = (calcList1 l) - (calcList2 l) 
    where 
        l = [0.0,step..2.0]

函数calcList1calcList2在每个列表上运行calc2函数,然后分别使用foldlfoldr对列表求和。 我期待这两个函数都返回相同的答案,但它不。

*Main> test1 0.1
9.536743e-7
*Main> test1 0.01
2.2888184e-5
*Main> test1 0.001
2.4414063e-4
*Main> test1 0.0001
-3.7109375e-2
*Main> 

现在我很困惑。 我看不出为什么数字问题必须涉及这里。 折叠本质上是如何收集在两种情况下应该相同的每个元素,对吗?


通常,添加浮点值的顺序非常重要。 自己研究的切入点可以是http://en.wikipedia.org/wiki/Loss_of_significance。 以简单的形式总结基本的警告:

由于有效位的数量有限,你必须假设类似的东西

 100000000000000000.0 + 1.0 = 100000000000000000.0

在浮点计算中。 因此,在计算时

  100000000000000000.0 
+                  1.0 
- 100000000000000000.0

结果将是0.0 - 因此,不同于

  100000000000000000.0 
- 100000000000000000.0
+                  1.0 

结果将是1.0

链接地址: http://www.djcxy.com/p/80731.html

上一篇: Numerical issue with `foldl` and `foldr` in Haskell

下一篇: Combining foldl and foldr