次の素朴な (一次) 有限差分関数を実装したいと思います。
finite_difference :: Fractional a => a -> (a -> a) -> a -> a
finite_difference h f x = ((f $ x + h) - (f x)) / h
ご存知かもしれませんが、微妙な問題があります。 とが正確に表現可能な数だけ異なることを確認する必要が(x + h)
あります。x
それ以外の場合、壊滅的なキャンセルを伴うという事実に影響されて、結果に大きなエラーが発生します(f $ x + h) - (f x)
(慎重に選択する必要がありますh
が、それは私の問題ではありません)。
C または C++ では、この問題は次のように解決できます。
volatile double temp = x + h;
h = temp - x;
volatile
修飾子は変数に関連する最適化を無効にするためtemp
、「賢い」コンパイラはこれらの 2 行を最適化しないことが保証されています。
これを解決する方法を知るには、まだ十分な Haskell を知りません。私はそれを恐れています
let temp = x + h
hh = temp - x
in ((f $ x + hh) - (f x)) / h
Haskell (または Haskell が使用するバックエンド) によって最適化されます。ここに相当するものを取得するにはどうすればよいですvolatile
か (怠惰を犠牲にすることなく可能であれば)? GHC固有の回答は気にしません。