「プログラムソース」 6−1、------------------------------------------------------------- #include #include #include #define N 5 #define eps 1.0e-10 void kai_kousiki(double *a,double *b,double *c) { double Re1,Re2,Im1,Im2,D; D = (*b) * (*b) - 4.0 * (*a) * (*c); if(D > 0){ Re1 = (-(*b) + sqrt(D)) / (2.0 * (*a)); Re2 = (-(*b) - sqrt(D)) / (2.0 * (*a)); Im1 = 0.0; Im2 = 0.0; } else if(D == 0){ Re1 = -(*b) / (2.0 * (*a)); Im1 = 0.0; } else{ Re1 = Re2 =-(*b) / (2.0 * (*a)); Im1 = sqrt(-D) / (2.0 * (*a)); Im2 = -Im1; } if(D == 0){ printf("%f + i %f\n",Re1,Im1); } else{ printf("%f + i %f\n",Re1,Im1); printf("%f + i %f\n",Re2,Im2); } } void bairstow(int n,double p[N+1]){ int i,max; double det,db,dc; double q[N+1],u[N+1],w[N+1]; double keisuu_3,keisuu_2,keisuu_1; max = 0; keisuu_3 = 1.0; while(1) { keisuu_2 = keisuu_1 = 1.0; do{ max++; if (max > 1000000) { printf("error!\n"); exit(1); } for(i=0; i<=n; i++) { if(i == 0) q[i] = p[i]; else if(i == 1) q[i] = p[i] - keisuu_2 * q[i-1]; else q[i] = p[i] - keisuu_2 * q[i-1] - keisuu_1 * q[i-2]; } for(i=0; i<=n; i++) { if(i == 0) u[i] = 0.0; else if(i == 1) u[i] = -q[i-1] - keisuu_2 * u[i-1]; else u[i] = -q[i-1] - keisuu_2 * u[i-1] - keisuu_1 * u[i-2]; } for(i=0; i<=n; i++) { if(i == 0) w[i] = 0.0; else if(i == 1) w[i] = -keisuu_2 * w[i-1]; else w[i] = -q[i-2] - keisuu_2 * w[i-1] - keisuu_1 * w[i-2]; } det = u[n-1] * w[n] - w[n-1] * (u[n] + q[n-1]); db = 1.0 / det * (q[n] * w[n-1] - q[n-1] * w[n]); dc = 1.0 / det * (-q[n] * u[n-1] + q[n-1] * (u[n] + q[n-1])); keisuu_2 += db; keisuu_1 += dc; }while( db * db + dc * dc > eps * eps ); for(i=0; i<=n-2; i++){ p[i] = q[i]; } if(n >= 3){ kai_kousiki(&keisuu_3,&keisuu_2,&keisuu_1); n -= 2; } else if(n == 2){ kai_kousiki(&p[0],&p[1],&p[2]); break; } else if(n == 1){ printf("%f + i 0.000000 \n",-p[1] / p[0]); break; } } } int main(){ int jisuu; double keisuu[N+1]={1.0, 4.0, -10.0, -26.0, -11.0, -30.0}; jisuu = N; bairstow(jisuu,keisuu); return 0; } -------------------------------------------------------------------------------- 「実行結果」 6−1-------------------------------------------------------------------------- C:\Documents and Settings\i865gpen4\デスクトップ\色んな資料\数値計算プログラミン グ\試験ソース>kadai6 0.000000 + i 1.000000 0.000000 + i -1.000000 3.000000 + i 0.000000 -2.000000 + i 0.000000   ←bcc32でコンパイルするとこの部分まで表示して、エラーとなる。 5.000000 + i 0.000000     ←gccでコンパイルするとエラーなく、きちんと動作する。 -------------------------------------------------------------------------------- 「考察」 bairstow法によって、5字方程式の解を求めるソースを作成した。 まず、コンパイラのgccでは何の問題もなく実行ファイルを動作することができたが、 なぜかフリーのコンパイラのbcc32でコンパイルすると、4つ目の解まで出力した後、 パソコンがエラーを出して、動作を停止させた。 この現象を調べるために、いろいろprintfでどこまでプログラムが実行されているのか調べたところ、 ソースの if(n >= 3){ kai_kousiki(&keisuu_3,&keisuu_2,&keisuu_1); n -= 2; の部分までは実行されていることがわかった。 n -= 2 の手前にprintfを記述したところ、そのprintfは表示されていたため、ここまではいけているみたいだ。 しかし、いろいろ試して見た結果、bcc32のほうはbairstow関数を抜けることが出来ていないみたいだ。 5つ目の解の手前、つまりは else if(n == 2){ kai_kousiki(&p[0],&p[1],&p[2]); break; } else if(n == 1){ printf("%f + i 0.000000 \n",-p[1] / p[0]); break; } の部分のどちらかで、エラーが起きているようである。 関数の部分も、型もきちんと同じになるようにしているため、エラーが起きる理由がわからない。 コンパイルは何の問題もなく通るために、余計にエラーの理由がわからなくなってしまった。 見た感じでは、どこが間違っているのかわからなかったので、gccで実行した方の動作結果を表示しておいた。 プログラムの構成としては、解の公式とbairstowの計算部分を関数として、bairstow関数内で解の公式の関数を呼び出し、 、またmain部分でbairstow関数を呼び出すようにしたため、このようなソースの順番となった。 --------------------------------------------------------------------------------