二分探索プログラムの添削願い
方程式の解を求める以下のプログラムの添削やアドバイスをお願いします。プログラムが行う処理手順の概要は、以下の通りです。解くべき方程式はmainの2行目に(i)と示されています。
(1)方程式を表示し、ユーザーに関数fのパラメーターを入力させる。
(2)関数の次数に応じて処理が分岐し、fが”定数項が0でない三次式”の場合は(4)へ飛ぶ。それ以外は(3)へ。
(3)解の公式などを用いて虚数解を含むすべての解を求めて表示し、終了。
(4)二分法を用いて解を求める。二分法の区間を入力するようユーザーを誘導する。
(5)設定された区間をさらに1000等分してそれぞれの区間に対して(上限値に近いほうから順番に)二分法を用い、見つけられるだけの実数解を探索し、結果を表示して終了。
・・・以上です。載せているソースコードは前文ではなく抜粋です。本当はソースコードを全部載せたかったのですが、字数制限の都合上かなり省略があります。
実際には、*には方程式のパラメータ入力への誘導部が、**には二分法の区間設定への誘導が省略されています。これらの部分で、関数のパラメータをa,b,c,dに、二分法の区間をupper,lowerに格納します。
また、ユーザーを誘導するメッセージ、求めた方程式の解を表示するメッセージなども全て省略しています。途中に出てくるメソッドですが、
・checkDegree(コードは省略されています。)
fのパラメータを渡すと、fの次数をdegreeに返す。
・soluteEq(コードは省略されています。)
fの次数とパラメータを渡すと、a=0かつd=0の場合を除き(i)の解を全て表示し、終了フラグを立てる。
・foo(省略されています。)
変数xと、方程式のパラメータを与えると、fの値を返す。
・doBisection
二分法の区間と方程式のパラメータを渡すとその区間を1000等分して新たな区間を
1000個作成し、それぞれの区間に(上限値に近いほうから)二分法を実行。見つけられた解の個数を返す。
となっています。
自分が作成したプログラムをEclipse上で動かしてみると、一応正確な答えは帰ってきました。
ただ自分の作ったプログラムの問題として、doBisectionの処理において、たまたまn番目の区間の下限値が方程式(i)の解だった場合、n+1番目の区間に対して二分法処理が行われないことです。
これはn番目の区間の下限値が、n+1番目の区間の上限値になってしまうためなのですが、何か良い解決策をご提示願えないでしょうか。
また他にも、ソースコードをより可読的にするための改善点などありましたら、
ご提案願えないでしょうか。プログラミング初学者なのですが、独学でやっていますので
変な癖がついたりするのが結構不安です。
以下ソースコード抜粋を貼ります。皆様のお言葉、お待ちしております・・・
(自分は返信をスルーすることはありません。ベストアンサーも必ず指定して質問を完結させます。)
//以下main methodの中身
double a = 0, b = 0, c = 0, d = 0, upper = 1, lower = 0;
System.out.println("f(x) = a * x^3 + b * x^2 + c * x + d = 0 ・・・(i).");//*
int degree = checkDegree(a,b,c,d);
int endflag = soluteEq(degree,a,b,c,d);
if(endflag == 1){return;}//**
if(upper == lower){return;}
if(upper < lower){
double change = lower;
lower = upper;
upper = change;
}
int find = doBisection(upper,lower,a,b,c,d);
}//main以上
//以下doBisection
int i = 0, find = 0;
while(true){
double u = (1 - 0.001*i)*upper + 0.001*i*lower;
double l = (1 - 0.001*(i+1))*upper + 0.001*(i+1)*lower;
if(find == 3){break;}
if(i == 999){break;}
while(true){
double fl = foo(l,a,b,c,d);
double fu = foo(u,a,b,c,d);
if(fu*fl > 0){
i++;
break;}
if(fl == 0){
find++;
i++;
break;}
if(fu == 0){
System.out.println("x = "+ u +"\r\nは方程式(i)の解です。");
find++;
i++;
break;}
if(u - l < 10E-10){
i++;
find++;
break;}
double m = (u + l) / 2;
double fm = foo(m,a,b,c,d);
if(fm == 0){
find++;
i++;
break;}
if(fu*fm > 0){u = m;}
if(fl*fm > 0){l = m;}
}
}
return find;
}//doBisection以上。
お礼
tangent peak bottom いずれも大変参考になりました tangent point なども見つかりましたので使いたいとおもいます ご回答まことにありがとうございました 良いお年でありますように!