ページ 11

ある行から下が実行されません。

Posted: 2012年11月28日(水) 19:43
by unittk501st
85行目以下が実行されません。
試しに setbuf(stdout, NULL); を使ってみたのですがダメでした…
どこを直せば良いでしょうか?ご教示下さい。

コード:

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

double func1(double x){
  double y;
  y=x+1/2-sqrt(1-x*x);
  return y;
}

double func2(double x){
  double y;
  y=x+1/2+sqrt(1-x*x);
  return y;
}

int i, j;/*グローバル変数*/

double NewtonRaphson(double (*func_p)(double), double init, double eps, int imax) {/*ニュートン法*/
  double x, x_n, f, df, h;
  x=init;
  i=0;
  h=1e-4;
  while (i<imax) {
    f=func_p(x);
    df=(func_p(x+h)-func_p(x))/h;
    x_n=x - f/df;/*ニュートン反復により次の点x_n を計算する部分*/
    if (fabs(x_n - x)<eps){/* 収束条件を満たしたら解を返す*/
      return x_n;
    }
    i++;/*カウンター*/
    x=x_n;
  }
  return 0.0/0.0; /* NaN を返す*/
}

double Bisection(double (*func_p)(double), double a, double b, double eps){/*二分法*/
  double c;
  c = (a+b)/2;
  j=1;
  while(fabs(a-b)>=2*eps){/*収束前のときループ*/
    c = (a+b)/2;
    j++;/*カウンター*/
    if(func_p(c)>0){/*bとf(c)が同符号のとき*/
      c = b;
    }
    if(func_p(c)<0){/*aとf(c)が同符号のとき*/
      c = a;
    }
    if(func_p(c)==0.0){/*f(c)=0のとき*/
      return c;
    }
  }
  return c;
}



int main(void){
  double x;
setbuf(stdout, NULL);
  printf("Newton-Raphson method:\n");/*ニュートン法*/

  printf("Upper part: ");/*関数1*/
  x = NewtonRaphson(func1, 0, 1e-6, 20);
  if (!isnan(x)){
	  printf("(%d times):( %+.6f, %+.6f )\n", i+1, x, func1(x));
  }else{
	  printf("not converged\n");
  }
  x=0;
  printf("Lower part: ");/*関数2*/
  x = NewtonRaphson(func2, 0, 1e-6, 20);
  if (!isnan(x)){
	  printf("(%d times):( %+.6f, %+.6f )\n", i+1, x, func2(x));
  }else{
	  printf("not converged\n");
  }
  x=0;

  printf("Bisection method:\n"); /*二分法*/
  printf("Upper part: "); /*関数1*/

/*ここから下が実行されません*/

  x = Bisection(func1, -1, 1, 1e-6);
  printf("(%d times):( %+.6f, %+.6f )\n", j, x, func1(x));
  x=0.0;
  printf("Lower part: ");/*関数2*/
  x = Bisection(func2, -1, 1, 1e-6);
  printf("(%d times):( %+.6f, %+.6f )\n", j, x, func2(x));
  x=0.0;


return 0;
}

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 19:55
by h2so5
「実行されない」とはどういう状況ですか?
途中でプログラムが終了するのか、それともブレークポイントを入れても一時停止しないのか、単に出力が無いのかどれでしょう。

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 20:01
by unittk501st
返信ありがとうございます。

「実行されない」とは、「プログラムが終了せず85行目以下が表示されない」という意味です。

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 20:31
by h2so5
それなら、Bisection関数の中で無限ループしている可能性が高いですね。

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 21:10
by box
unittk501st さんが書きました:

コード:

  y=x+1/2-sqrt(1-x*x);
  y=x+1/2+sqrt(1-x*x);
この2行、1/2は整数どうしの割り算ですから結果はゼロです。つまり、

コード:

  y=x-sqrt(1-x*x);
  y=x+sqrt(1-x*x);
こう書いたのと同じです。
そうなることをお望みでしょうか?

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 22:19
by box
unittk501st さんが書きました:85行目以下が実行されません。

コード:

    if(func_p(c)==0.0){/*f(c)=0のとき*/
      return c;
    }
ここの判定において、「厳密に」0.0と比較しなければなりませんか?

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 22:26
by みけCAT
二分探索の終了条件をEPSを用いて判断すると終了しないことがあるため、
「値が変化しなくなったら終了」という条件をおすすめします。
コード例(平方根を求める)

コード:

double mysqrt(double target) {
	double left,right,mid,now;
	left=0;right=(target<=1?1:target);
	while(1) {
		mid=(left+right)/2;
		now=mid*mid;
		if(now<target) {
			if(left==mid)break;
			left=mid;
		} else {
			if(right==mid)break;
			right=mid;
		}
	}
	return mid;
}
この場合

コード:

double Bisection(double (*func_p)(double), double a, double b, double eps){/*二分法*/
  double c;
  c = (a+b)/2;
  j=1;
  while(fabs(a-b)>=2*eps){/*収束前のときループ*/
    c = (a+b)/2;
    j++;/*カウンター*/
    if(func_p(c)>0){/*bとf(c)が同符号のとき*/
      if(c==b)return c;
      c = b;
    }
    if(func_p(c)<0){/*aとf(c)が同符号のとき*/
      if(c==a)return c;
      c = a;
    }
    if(func_p(c)==0.0){/*f(c)=0のとき*/
      return c;
    }
  }
  return c;
}
とするということです。

重要
Bisection関数内では、条件分岐のあとcではなくaやbを更新しないといけません。

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 22:31
by box
unittk501st さんが書きました:85行目以下が実行されません。

コード:

    if(func_p(c)>0){/*bとf(c)が同符号のとき*/
      c = b;
    }
ここで、c の値を上書きする可能性がありますね。その上書きした c の値を
unittk501st さんが書きました:

コード:

    if(func_p(c)<0){/*aとf(c)が同符号のとき*/
      c = a;
    }
ここで本当に使っていいのかな?という疑問があります。
本当は

コード:

    else if(func_p(c)<0){/*aとf(c)が同符号のとき*/
      c = a;
    }
だったりするのではないでしょうか。

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 22:34
by box
どうやら、私の回答はいいかげんな内容みたいですので、
他の回答者さんの助言に従ってください。

Re: ある行から下が実行されません。

Posted: 2012年11月28日(水) 22:36
by みけCAT
大事なことなので二度言います。

コード:

if(func_p(c)>0){/*bとf(c)が同符号のとき*/
  if(c==b)return c;
  c = b;
}
if(func_p(c)<0){/*aとf(c)が同符号のとき*/
  if(c==a)return c;
  c = a;
}
ここでcの値を更新しても

コード:

c = (a+b)/2;
でもとのcの値に戻り、無限ループが発生します。
本当は、cではなくaやbの値を更新するべきではありませんか?