ニュートン法による近似根の計算 (C 言語)

CBeginner
オンラインで実践に進む

はじめに

この実験では、ニュートン法を用いて関数の根を近似する方法を C 言語で学ぶことを目的とします。この実験では以下の手順を踏みます。

まず、関数 f(x) とその導関数 f'(x) を定義します。次に、ニュートン法の反復式を実装して近似根を計算します。最後に、結果として得られた近似根を出力します。

この実験は、数値計算手法を C プログラミングを用いて数学的問題を解決する際の実際的な例を示しています。実験の終わりまでに、ニュートン法を用いて関数の根を求める方法をより深く理解できるでしょう。

f(x) と f'(x) の定義

このステップでは、ニュートン法を用いて根を近似するために、数学関数 f(x) とその導関数 f'(x) を定義します。

まず、~/project ディレクトリに新しい C ファイルを作成します。

cd ~/project
nano newton_method.c

次に、関数とその導関数を定義する初期コードを記述します。

#include <stdio.h>
#include <math.h>

// 関数 f(x) を定義
double f(double x) {
    return x * x - 4;  // 例題関数:f(x) = x^2 - 4
}

// 導関数 f'(x) を定義
double f_derivative(double x) {
    return 2 * x;  // f(x) = 2x の導関数
}

int main() {
    printf("関数 f(x) = x^2 - 4\n");
    printf("導関数 f'(x) = 2x\n");
    return 0;
}

出力例:

関数 f(x) = x^2 - 4
導関数 f'(x) = 2x

コードの詳細:

  • f(x)x^2 - 4 と定義されており、x = 2 と x = -2 に根があります。
  • f_derivative(x) は f(x) の導関数で、2x です。
  • これらの関数は、次のステップでニュートン法を実装するために使用されます。

コードをコンパイルして確認します。

gcc -o newton_method newton_method.c -lm
./newton_method

x_{n+1} = x_n - f(x_n)/f'(x_n) の反復計算

このステップでは、関数の根を近似するためのニュートン法の反復式を実装します。

以前の newton_method.c ファイルを開きます。

cd ~/project
nano newton_method.c

ニュートン法の反復計算を含めるようにコードを更新します。

#include <stdio.h>
#include <math.h>

// 前の関数定義は同じです
double f(double x) {
    return x * x - 4;
}

double f_derivative(double x) {
    return 2 * x;
}

// ニュートン法の実装
double newton_method(double initial_guess, int max_iterations, double tolerance) {
    double x = initial_guess;

    for (int i = 0; i < max_iterations; i++) {
        double fx = f(x);
        double fpx = f_derivative(x);

        // ゼロ除算を防ぐ
        if (fabs(fpx) < tolerance) {
            printf("導関数がゼロに近すぎます。計算を続行できません。\n");
            return x;
        }

        // ニュートン法の反復式
        double x_next = x - fx / fpx;

        printf("反復 %d: x = %f\n", i + 1, x_next);

        //収束の確認
        if (fabs(x_next - x) < tolerance) {
            return x_next;
        }

        x = x_next;
    }

    printf("最大反復回数に達しました。\n");
    return x;
}

int main() {
    double initial_guess = 1.0;
    int max_iterations = 10;
    double tolerance = 1e-6;

    double root = newton_method(initial_guess, max_iterations, tolerance);

    printf("\n近似根:%f\n", root);
    printf("f(根) = %f\n", f(root));

    return 0;
}

コードをコンパイルして実行します。

gcc -o newton_method newton_method.c -lm
./newton_method

出力例:

反復 1: x = 2.500000
反復 2: x = 2.050000
反復 3: x = 2.000610
反復 4: x = 2.000000
反復 5: x = 2.000000

近似根: 2.000000
f(根) = 0.000000

実装に関する重要な点:

  • newton_method() は初期値、最大反復回数、許容誤差を取ります。
  • ニュートン法の反復式:x_{n+1} = x_n - f(x_n) / f'(x_n) を実装します。
  • 収束の確認とゼロ除算の回避を行います。
  • 近似過程を示すために、中間反復を出力します。

近似根の表示

このステップでは、ニュートン法の実装を強化して、根の近似に関する詳細な出力を提供します。

以前の newton_method.c ファイルを開きます。

cd ~/project
nano newton_method.c

コードを更新して、根の近似出力内容を改善します。

#include <stdio.h>
#include <math.h>

// 前の関数とメソッドの定義は同じです
double f(double x) {
    return x * x - 4;
}

double f_derivative(double x) {
    return 2 * x;
}

double newton_method(double initial_guess, int max_iterations, double tolerance) {
    double x = initial_guess;

    printf("ニュートン法による根の近似\n");
    printf("-----------------------------------\n");
    printf("初期値:%f\n", x);
    printf("許容誤差:%e\n", tolerance);
    printf("最大反復回数:%d\n\n", max_iterations);

    for (int i = 0; i < max_iterations; i++) {
        double fx = f(x);
        double fpx = f_derivative(x);

        if (fabs(fpx) < tolerance) {
            printf("エラー: 導関数が許容誤差に近すぎます。\n");
            return x;
        }

        double x_next = x - fx / fpx;

        printf("反復 %d:\n", i + 1);
        printf("  現在の x: %f\n", x_next);
        printf("  f(x): %f\n", f(x_next));
        printf("  |x_next - x|: %e\n\n", fabs(x_next - x));

        if (fabs(x_next - x) < tolerance) {
            printf("収束しました!\n");
            return x_next;
        }

        x = x_next;
    }

    printf("最大反復回数に達しました。\n");
    return x;
}

int main() {
    double initial_guess = 1.0;
    int max_iterations = 10;
    double tolerance = 1e-6;

    double root = newton_method(initial_guess, max_iterations, tolerance);

    printf("最終結果:\n");
    printf("-------------\n");
    printf("近似根:%f\n", root);
    printf("f(根): %f\n", f(root));
    printf("絶対誤差:%e\n", fabs(f(root)));

    return 0;
}

コードをコンパイルして実行します。

gcc -o newton_method newton_method.c -lm
./newton_method

出力例:

ニュートン法による根の近似
-----------------------------------
初期値: 1.000000
許容誤差: 1.000000e-06
最大反復回数: 10

反復 1:
  現在の x: 2.500000
  f(x): 2.250000
  |x_next - x|: 1.500000e+00

反復 2:
  現在の x: 2.050000
  f(x): 0.202500
  |x_next - x|: 4.500000e-01

... (反復の続き)

収束しました!

最終結果:
-------------
近似根: 2.000000
f(根): 0.000000
絶対誤差: 0.000000e+00

主な改善点:

  • 反復情報の詳細を追加
  • 初期パラメータを表示
  • 収束状況を表示
  • 絶対誤差を含む最終結果を表示

まとめ

この実験では、最初に数学関数 f(x) とその導関数 f'(x) を定義し、ニュートン法を用いて根を近似しました。次に、反復式 x_{n+1} = x_n - f(x_n)/f'(x_n) を実装して根の近似を行いました。最後に、このプロセスで得られた近似根を表示します。

この実験で扱った主な手順は、対象となる関数とその導関数を定義し、ニュートン法の式を反復的に適用して根に収束させることです。このアプローチを用いることで、C プログラミングを用いて様々な数学関数の根を効率的に求めることができます。