#include <iostream> #include <iomanip> void PrintArray(const double *pArray, int col, int row) { for(int i=0; i<col; ++i) { for(int j=0; j<row; ++j) { std::cout << std::setw(10) << pArray[i*row+j] << " "; } std::cout << std::endl; } std::cout << "------------------------------" << std::endl; } // 入力用データ // x,y,z = 2, 3, 4 // 2x + 3y + 2z = 21 (1) // 3x + 4y + 3z = 30 (2) // 5x + 2y + 4z = 32 (3) double mat[4*4] = { 2, 3, 2, 21, 3, 4, 3, 30, 5, 2, 4, 32, 1, 1, 1, 1, }; int main(int argc, char **argv) { //計算用配列 double tmp[4*4] = {1}; //まずは(1)式のxの係数を1にする for(int i=0; i<4; ++i) { tmp[i] = mat[i] / mat[0]; } PrintArray(tmp, 4, 4); //(2),(3)式のxの係数を1に合わせる for(int i=0; i<4; ++i) { tmp[1*4+i] = mat[1*4+i] / mat[1*4]; tmp[2*4+i] = mat[2*4+i] / mat[2*4]; } PrintArray(tmp, 4, 4); //(1)式から(2),(3)式を引いたものをtmp[2,3][0-3]に格納 for(int i=0; i<4; ++i) { tmp[1*4+i] = tmp[0*4+i] - tmp[1*4+i]; tmp[2*4+i] = tmp[0*4+i] - tmp[2*4+i]; } PrintArray(tmp, 4, 4); //次に(2)式のyの係数と(3)式のyの係数を合わせる double yk = tmp[1*4+1] / tmp[2*4+1]; for(int i=1; i<4; ++i) { tmp[2*4+i] = tmp[2*4+i] * yk; } PrintArray(tmp, 4, 4); //(2)式から(3)式を引く for(int i=1; i<4; ++i) { tmp[2*4+i] = tmp[1*4+i] - tmp[2*4+i]; } PrintArray(tmp, 4, 4); //z成分を求める double z = tmp[3*4+2] = tmp[2*4+3] / tmp[2*4+2]; PrintArray(tmp, 4, 4); //y成分を求める double y = tmp[3*4+1] = (tmp[1*4+3] - (z*tmp[1*4+2])) / tmp[1*4+1]; PrintArray(tmp, 4, 4); //xを求める double x = tmp[3*4+0] = (tmp[0*4+3] - (z*tmp[0*4+2] + y*tmp[0*4+1])) / tmp[0*4+0]; PrintArray(tmp, 4, 4); std::cout <<"(x,y,z) = (" << x << ", " << y << ", " << z << ")" << std::endl; return 0; }どうでもいいがなんで2次元配列使わなかったんだろう俺…。あと所々でPrintArrayを呼び出してるのはデバッグのためです。あしからず。
2010年4月27日火曜日
3元連立方程式をガウスの消去法で解いてみた
タイトルまんまです(ガウスの消去法についてはwiki参照のこと)。逆行列を求めるのに似たような方法を使うのですが、微妙に忘れかけてたので復習を兼ねて解いてみた。本当は精度の問題とかもあって、もっとちゃんとしたアルゴリズムがあるらしいが、そんなのは知らん。あまりにひどいハードコーディングなので、明日はN元まで拡張するつもり。
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿