ONLY DO WHAT ONLY YOU CAN DO

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

Ada で非線形方程式を解く (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\}

with TEXT_IO, Ada.Long_Float_Text_IO, Ada.Numerics.Long_Elementary_Functions;
use  TEXT_IO, Ada.Long_Float_Text_IO, Ada.Numerics.Long_Elementary_Functions;

procedure Ada0901 is

    function f(x:Long_Float) return Long_Float is
    begin
        return x * x - 2.0;
    end f;

    a: Long_Float := 1.0;
    b: Long_Float := 2.0;
    c: Long_Float;
    fc: Long_Float;
begin
    while true loop
        -- 区間 (a, b) の中点 c = (a + b) / 2
        c := (a + b) / 2.0;
        Put(a,       Fore=>2, Aft=>10, Exp=>0);
        Put(Ascii.HT);
        Put(b,       Fore=>2, Aft=>10, Exp=>0);
        Put(Ascii.HT);
        Put(c,       Fore=>2, Aft=>10, Exp=>0);
        New_Line;

        fc := f(c);
        If Abs(fc) < 0.0000000001 then 
            exit;
        end if;
        
        if fc < 0.0 then
            -- f(c) < 0 であれば, 解は区間 (c, b) の中に存在
            a := c;
        else
            -- f(c) > 0 であれば, 解は区間 (a, c) の中に存在
            b := c;
        end if;
    end loop;

    Put(c,       Fore=>2, Aft=>10, Exp=>0);
    Put(Ascii.HT);
    Put(Sqrt(2.0), Fore=>2, Aft=>10, Exp=>0);
    New_Line;
end Ada0901;
 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.4145507813
 1.4140625000	 1.4145507813	 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
 1.4142135605	 1.4142135642	 1.4142135624
 1.4142135624	 1.4142135624
参考文献