Strange behavior when calculating numerical derivatives

I’ve encountered a strange behavior when calculating numerical derivatives, where I don’t know what the problem is. Maybe someone could help. I’ve tried the following code in the Haskell playground. Every ghc version shows the same results. If I write two different versions of the derivative function (one with forward and one with backward difference) and try different combinations when calculating the second derivative, I get correct results.

derivative :: (Double -> Double) -> Double -> Double
derivative f x = cases where
    h = 0.000001
    delta_f_plus  = f (x + h) - f x -- forward difference
    delta_f_minus = f x - f (x - h) -- backward difference
    cases 
         | abs delta_f_plus <= abs delta_f_minus = delta_f_plus/h
         | otherwise = delta_f_minus/h

derivativeF :: (Double -> Double) -> Double -> Double
derivativeF f x = cases where
    h = 0.000001
    delta_f_plus  = f (x + h) - f x
    cases = delta_f_plus/h

derivativeB :: (Double -> Double) -> Double -> Double
derivativeB f x = cases where
    h = 0.000001
    delta_f_minus = f x - f (x - h)
    cases = delta_f_minus/h

main :: IO ()
main = do
    let f x = (cos x)^2
    -- Calculate f'' 0, must be approx -2:

    -- This works:
    let f' x = derivativeF f x
    let f'' x = derivativeF f' x
    putStrLn $ show (f'' 0) 
    
    -- This works:
    let f' x = derivativeF f x
    let f'' x = derivativeB f' x
    putStrLn $ show (f'' 0) 

    -- This works:
    let f' x = derivativeB f x
    let f'' x = derivativeF f' x
    putStrLn $ show (f'' 0) 

    -- This works:
    let f' x = derivativeB f x
    let f'' x = derivativeB f' x
    putStrLn $ show (f'' 0) 

    -- This works not:
    let f' x = derivative f x
    let f'' x = derivative f' x
    putStrLn $ show (f'' 0) 
1 Like

I think the problem is that your derivative function is not continuous (it is discontinuous in k*pi/2 which includes 0). It is a function that is equal to derivativeF on some inputs and equal to derivativeB on other parts.

See: Graphing Calculator

3 Likes

Thank you, I think you are right that the problem is that the derivative function is not continous and therefore not differentiable. The functions derivativeF and derivativeB on the other hand both are differentiable, so composition of them also is differentiable. This is tricky, since I’ve got nearly the same results for all 5 combinations at positions different from 0. So I was lucky to try out 0 in the first place.

1 Like