[改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いします。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
yyy

[改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いします。

#1

投稿記事 by yyy » 9年前

f(x)=x^3-4x^2+x+12の近似解を求めるのですが、解が0.000010,0.000000 となりおかしいのですがどこを正すべきでしょうか。

コード:

#include <stdio.h>

int main(void)
{
  double eps=0.00001;
  printf("%lf %lf\n",eps);
double f(double x)
{
  return x*x*x-4*x*x+x+12;
}
double g(double x1,double x2,double eps)
{
  double x;
  while(x2-x1>=eps)
    {
      x=(x1+x2)/2.0;
      if(f(x1)*f(x)>0.0)
        {
          x1=x;
        }
      else
        {
          x2=x;
        }
    }
  return (x1+x2)/2.0;
    }
 return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いし

#2

投稿記事 by みけCAT » 9年前

まず、改善したコードを元のトピックに書き込まず新しいトピックにしようという考えを正すべきです。
その上で、
  • 現状ではepsをそのまま出力していており、全く解を求めていません。g()を宣言して何らかの形で呼び出すべきでしょう。
  • フォーマットに対してprintfに渡す引数が足りないので、未定義動作です。データを増やすか、変換指定子を減らさなければいけません。
  • 関数の中で関数を定義するのは標準ではできず、GCC拡張なので、必要が無ければやるべきではありません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

box
記事: 2002
登録日時: 14年前

Re: [改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いし

#3

投稿記事 by box » 9年前

定義した関数g(mainの中にあるのが気持ち悪いけど)をどこで呼び出しているんですか?
なんか二分法の前に勉強することがたくさんありそうに思えてなりません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

かずま

Re: [改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いし

#4

投稿記事 by かずま » 9年前

yyy さんが書きました:f(x)=x^3-4x^2+x+12の近似解を求めるのですが、解が0.000010,0.000000 となりおかしいのですがどこを正すべきでしょうか。
main から g を適切に呼び出して、返ってきた結果を表示すればよいでしょう。

コード:

#include <stdio.h>

double f(double x) { return x*x*x - 4*x*x + x + 12; }

double g(double x1, double x2, double eps)
{
    while (x2 - x1 >= eps) {
        double x = (x1 + x2) / 2;
        if (f(x1) * f(x) > 0)
            x1 = x;
        else
            x2 = x;
    }
    return (x1 + x2) / 2;
}

int main(void)
{
    printf("%f\n", g(-10, 10, 0.0000001));
    return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いし

#5

投稿記事 by みけCAT » 9年前

かずま さんが書きました:

コード:

    printf("%f\n", g(-10, 10, 0.0000001));
この呼び出し方は区間内で対象の関数が単調増加も単調減少もしないので、適切ではありません。

この関数f(x)をプロットするとこうなります。
nibunhou-20160625.png
関数のグラフ
nibunhou-20160625.png (13.34 KiB) 閲覧数: 2767 回
これだけではわかりにくいですが、導関数をプロットすると符号が変わることがわかります。
nibunhou-bibun-20160625.png
導関数のグラフ
nibunhou-bibun-20160625.png (17.65 KiB) 閲覧数: 2767 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: [改訂版]2分法を使ってf(x)=0の解を求めるプログラムについて、間違っている箇所がわからないので訂正お願いし

#6

投稿記事 by かずま » 9年前

みけCAT さんが書きました:
かずま さんが書きました:

コード:

    printf("%f\n", g(-10, 10, 0.0000001));
この呼び出し方は区間内で対象の関数が単調増加も単調減少もしないので、適切ではありません。
なるほど、(4-√13)/3 < x < (4+√13)/3、
すなわち 0.1314... < x < 2.535... では、f(x) は減少していますね。

[-10, 10] の範囲を指定したとき、最初の 1回で [-10, 0] になったから
たまたま解が求まっていたようです。

g(-10, 0, 0.00001) とか、g(-5, 0, 0.00001) とかで呼び出さないと、
適切な呼び出しとは言えませんね。

ご指摘ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る