我有以下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]
功能calcList1
和calcList2
在每个列表上运行calc2
函数,然后分别使用foldl
和foldr
对列表求和。我期待这两个函数都返回相同的答案,但事实并非如此。
*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>
现在我很困惑。我不明白为什么必须在这里涉及数字问题。折叠本质上是收集每个元素的方式,在两种情况下都应该相同,对吗?
答案 0 :(得分:16)
通常,添加浮点值的 order 非常重要。自己研究的切入点可能是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
。