未分類未分類
挟み撃ち法; False Position Method

概要
挟み撃ち法は関数値が0を通る点を求める求根アルゴリズムの一つ。領域の端2点を通る直線とx軸との交点を新たな領域の端とすることを繰り返し根を求める
二分法より収束速度が早く、ニュートン法より確実な手法である。
二分法

アルゴリズム
\(f(x)=0\)となる\(x\)を求める。
・初期値
-根を含む領域\([a, b]\)を設定する。

・収束計算
-領域の端2点を通る直線とx軸との交点を求める。
\(\quad \displaystyle c = a + (a - b) \frac{f(a)} {f(b) - f(a)} \)
-\(f(a), f(c)\)の符号が一致するなら\(c\)を新たな\(a\)と、\(f(c), f(b)\)の符号が一致するなら\(c\)を新たな\(b\)とする。

ソースコード

namespace RootFindingMethod {

    /// <summary>挟み撃ち法</summary>
    /// <remarks>f(x)=0となるxを求める</remarks>
    public static class FalsePositionMethod {

        /// <summary>求根</summary>
        /// <param name="func">f(x)=0となる関数f(x)</param>
        /// <param name="xa">求根範囲</param>
        /// <param name="xb">求根範囲</param>
        /// <param name="precision_level">精度レベル</param>
        /// <remarks>f(xa), f(xb)は異符号である必要がある</remarks>
        public static double Execute(Func<double, double> func, double xa, double xb, int precision_level) {
            double a = func(xa), b = func(xb), c, xc = xa;

            if((a > 0 && b > 0) || (a < 0 && b < 0)) {
                throw new ArgumentException($"Invalid Range {nameof(xa)}, {nameof(xb)}");
            }

            while(precision_level > 0) {
                xc = xa + (xa - xb) * (a / (b - a));
                c = func(xc);
                precision_level--;

                if((a > 0 && c > 0) || (a < 0 && c < 0)) {
                    xa = xc;
                    a = c;
                    continue;
                }
                if((b > 0 && c > 0) || (b < 0 && c < 0)) {
                    xb = xc;
                    b = c;
                    continue;
                }
                break;
            }

            return xc;
        }
    }
}

単体テスト

namespace RootFindingMethod.Tests {
    [TestClass()]
    public class FalsePositionMethodTests {
        [TestMethod()]
        public void ExecuteTest1() {
            Func<double, double> func = (x) => x * x - 2;

            double v = FalsePositionMethod.Execute(func, 0, 2, 20);

            Assert.AreEqual(v, Math.Sqrt(2), 1e-14);
        }
    
        [TestMethod()]
        public void ExecuteTest2() {
            Func<double, double> func = (x) => x * x - 2;

            double v = FalsePositionMethod.Execute(func, 2, 0, 20);

            Assert.AreEqual(v, Math.Sqrt(2), 1e-14);
        }
    }
}


関連項目
ニュートンラフソン法
二分法
割線法

ライブラリライブラリ
確率統計確率統計
線形代数線形代数
幾何学幾何学
最適化最適化
微分方程式微分方程式
画像処理画像処理
補間補間
機械学習機械学習
クラスタリングクラスタリング
パズルゲーム・パズル
未分類未分類