数値解析課題-ヤコビ法,ガウス・ザイテル法
3次の行列しか対応せず
解が収束しない場合の対応は考えていない
一応動くけど細かい動作は未検証
プログラム的にはLU分解よりなんぼか簡単
ちょっと修正.
// 数値解析-ヤコビ・ガウスザイテル法.cpp // 解が収束しなかった場合の処理は特に考えていない #include "stdafx.h" #include "iostream" #include "cstdio" #include "cmath" #define N 3 #define EPSI 0.001 //ε #define LMT 100000 //最大反復回数 bool converge_judge(void); //収束(事前)判定 int yakobi(void); int gaussdel(void); double mat[N][N] = { { 9.0, 3.0, 5.0 }, //簡単のためグローバル変数 { 2.0, 9.0, 6.0 }, { 4.0, 3.0, 9.0 } }; double b[N] = { 30.0, 38.0, 37.0 }; double x[N] = { 0.0, 0.0, 0.0 }; //解を格納 double x2[N]; //解を一時的に格納(ヤコビ法で使用) int main(int argc, _TCHAR* argv[]) { int c; if (converge_judge() == true){ printf("収束判定:真\n"); } //c = gaussdel(); //ガウスザイテル法 c = yakobi(); //ヤコビ法 printf("x={ %1.3lf, %1.3lf, %1.3lf }\n",x[0],x[1],x[2]); //解の表示 printf("反復回数:%d\n",c); return 0; } bool converge_judge(void){ //収束判定(解が収束するかどうか) for(int i = 0;i < N ;i++){ for(int j = 0;j < N;j++){ if(i !=j){ if(mat[i][i] < mat[i][j]){ return false; } } } } return true; } int yakobi(void){ //ヤコビ法 double s = 0.0, emax = 0.0; for(int c = 0;c < LMT;c++){ emax = 0.0; for(int i = 0;i < N;i++){ s = b[i]; for(int j = 0;j < N;j++){ s -= mat[i][j] * x[j]; } s = s / mat[i][i]; x2[i] = x[i] + s; if(x[i] != 0){ if(emax < fabs(1 - (x2[i] / x[i]) )){ //相対誤差の最大を求める emax = fabs(1 - (x2[i] / x[i]) ); } } else{ //ループの1回目で終了しないように emax = 1.0; } } for(int k = 0;k < N;k++){ x[k] = x2[k]; } if(emax <= EPSI){ return c; } } return 0; //解が収束しなかった } int gaussdel(void){ //ガウス・ザイテル法 double s = 0.0, e = 0.0, emax = 0.0; for(int c = 0;c < LMT;c++){ emax = 0.0; for(int i = 0;i < N;i++){ s = b[i]; for(int j = 0;j < N;j++){ s -= mat[i][j] * x[j]; } s = s / mat[i][i]; e = x[i] + s; //上書きする前に相対誤差を求める if(x[i] != 0){ if(emax < fabs(1 - (e / x[i]) )){ emax = fabs(1 - (e / x[i]) ); } } else{ //ループの1回目で終了しないように emax = 1.0; } x[i] = e; } if(emax <= EPSI){ return c; } } return 0; //解が収束しなかった