ONLY DO WHAT ONLY YOU CAN DO

こけたら立ちなはれ 立ったら歩きなはれ

Haskell で非線形方程式を解く (2分法)

非線形方程式の解法(2分法)を利用して2の平方根を求める

f:id:fornext1119:20140531160605p:plain
1. まず, 条件 a < b, f(a) < 0, f(b) > 0 を満たす点 a, b を考えると,
関数 f(x) の解は, 区間 (a,b) の中に存在する.
2. 次に, 区間 (a,b) の中点 c = (a + b) / 2 を考えると,
f(c) < 0 であれば, 解は区間 (c,b) の中に存在し,
同様に, f(c) > 0 であれば, 区間 (a,c) の中に存在する.
3. この作業を繰り返して, 区間を絞り込んで行くことで解を求める.

※ちなみに, 区間 (a,b) とは, 両端を含まない数の集合で, 開区間という
 (a, b) = \{x | a < x < b\}
また, 両端を含む数の集合は, 閉区間という
 [a, b] = \{x | a ≤ x ≤ b\}

import Text.Printf
import Debug.Trace

f::Double->Double
f x = x * x - 2.0

bisection::Double->Double->Double
bisection a b =
    let
        -- 区間 (a, b) の中点 c = (a + b) / 2
        c = (a + b) / 2.0
        fc = (f c) :: Double
    in
        if abs(fc) < 0.0000000001 then
            c
        else
            if fc < 0.0
                then
                    -- f(c) < 0 であれば, 解は区間 (c, b) の中に存在
                    trace (printf "%12.10f\t%12.10f\t%12.10f" a b c)
                    bisection c b
                else
                    -- f(c) > 0 であれば, 解は区間 (a, c) の中に存在
                    trace (printf "%12.10f\t%12.10f\t%12.10f" a b c)
                    bisection a c

main = do
    let a = 1.0
    let b = 2.0
    let c = (bisection a b)
    printf "%12.10f\t%12.10f\n" c ((sqrt 2.0)::Double)
1.4142135624	1.4142135624
1.0000000000	2.0000000000	1.5000000000
1.0000000000	1.5000000000	1.2500000000
1.2500000000	1.5000000000	1.3750000000
1.3750000000	1.5000000000	1.4375000000
1.3750000000	1.4375000000	1.4062500000
1.4062500000	1.4375000000	1.4218750000
1.4062500000	1.4218750000	1.4140625000
1.4140625000	1.4218750000	1.4179687500
1.4140625000	1.4179687500	1.4160156250
1.4140625000	1.4160156250	1.4150390625
1.4140625000	1.4150390625	1.4145507812
1.4140625000	1.4145507812	1.4143066406
1.4140625000	1.4143066406	1.4141845703
1.4141845703	1.4143066406	1.4142456055
1.4141845703	1.4142456055	1.4142150879
1.4141845703	1.4142150879	1.4141998291
1.4141998291	1.4142150879	1.4142074585
1.4142074585	1.4142150879	1.4142112732
1.4142112732	1.4142150879	1.4142131805
1.4142131805	1.4142150879	1.4142141342
1.4142131805	1.4142141342	1.4142136574
1.4142131805	1.4142136574	1.4142134190
1.4142134190	1.4142136574	1.4142135382
1.4142135382	1.4142136574	1.4142135978
1.4142135382	1.4142135978	1.4142135680
1.4142135382	1.4142135680	1.4142135531
1.4142135531	1.4142135680	1.4142135605
1.4142135605	1.4142135680	1.4142135642
参考文献