Reputation: 1133
I have a question regarding numerical operations in Haskell.
I have a basic function:
derv::(Num a, Fractional a) => (a -> a) -> a -> a -> a
derv f a deltax = ((f (a+deltax))-(f a))/deltax
When I test it, this is the output I get:
*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>
When the divisor gets smaller, it makes the answer automatically go towards zero, rather than a more refined convergence toward 4. I'm curious as to why this is happening, especially given my type definition.
Upvotes: 1
Views: 96
Reputation: 116164
In your code the 0.000000000000000001
is probably being defaulted
to Double
, causing
a loss of precision after 2
is added because of rounding.
Using an exact representation such as Rational
does not exhibit the same issue:
> import Data.Ratio
> derv (\x->x*x) 2 0.000000000000000001 :: Rational
4000000000000000001 % 1000000000000000000
> fromRational (derv (\x->x*x) 2 0.000000000000000001) :: Double
4.0
In the last line the loss of precision happens after the incremental ratio is computed, so the result is close to the exact fraction shown above.
Upvotes: 3