我对Haskell中的数值运算有疑问。
我有一个基本功能:
derv::(Num a, Fractional a) => (a -> a) -> a -> a -> a
derv f a deltax = ((f (a+deltax))-(f a))/deltax
当我测试它时,这是我得到的输出:
*Main> derv (\x->x*x) 2 0.000000000000000001
0.0
*Main> derv (\x->x*x) 2 0.00000000000001
4.085620730620576
*Main> derv (\x->x*x) 2 0.0000000001
4.000000330961484
*Main> derv (\x->x*x) 2 0.0001
4.0001000000078335
*Main>
当除数变小时,它会使答案自动趋向零,而不是向4更精确的收敛。我很好奇为什么会发生这种情况,特别是考虑到我的类型定义。
答案 0 :(得分:3)
在您的代码中,0.000000000000000001
可能是defaulted
到Double
,导致
由于四舍五入,添加2
后精度会下降。
使用Rational
之类的精确表示不会出现同样的问题:
> import Data.Ratio
> derv (\x->x*x) 2 0.000000000000000001 :: Rational
4000000000000000001 % 1000000000000000000
> fromRational (derv (\x->x*x) 2 0.000000000000000001) :: Double
4.0
在最后一行中,在计算增量比后发生精度损失,因此结果接近上面显示的精确分数。
答案 1 :(得分:0)
这可能是由于浮点舍入错误造成的。您可以使用固定点编号,如here所示。