静岡理工科大学 菅沼ホーム 目次 索引

連立線形方程式と逆行列

    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

  プログラムは,連立線形方程式の解(逆行列)をガウスの消去法によって求めた例です.例として,
2 1
1 1
		
の逆行列を求めています.

  1. C++

    /****************************/
    /* 逆行列の計算             */
    /*      例: 2 1            */
    /*           1 1            */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    
    int gauss(double **, int, int, double);
    
    int main ()
    {
    	double **w, eps;
    	int i1, ind, n = 2, m = 2;
    /*
              データの設定
    */
    	w = new double * [n];
    	for (i1 = 0; i1 < n; i1++)
    		w[i1] = new double [n+m];
    
    	eps     = 1.0e-10;
    	w[0][0] = 2.0;
    	w[0][1] = 1.0;
    	w[0][2] = 1.0;
    	w[0][3] = 0.0;
    	w[1][0] = 1.0;
    	w[1][1] = 1.0;
    	w[1][2] = 0.0;
    	w[1][3] = 1.0;
    /*
              実行と出力
    */
    	ind = gauss(w, n, m, eps);
    
    	printf("ind = %d\n", ind);
    	printf("     %f %f\n", w[0][2], w[0][3]);
    	printf("     %f %f\n", w[1][2], w[1][3]);
    
    	return 0;
    }
    
    /*******************************************************/
    /* 線形連立方程式を解く(逆行列を求める)              */
    /*      w : 方程式の左辺及び右辺                       */
    /*      n : 方程式の数                                 */
    /*      m : 方程式の右辺の列の数                       */
    /*      eps : 逆行列の存在を判定する規準               */
    /*      return : =0 : 正常                             */
    /*               =1 : 逆行列が存在しない               */
    /*******************************************************/
    #include <math.h>
    
    int gauss(double **w, int n, int m, double eps)
    {
    	double y1, y2;
    	int ind = 0, nm, m1, m2, i1, i2, i3;
    
    	nm = n + m;
    
    	for (i1 = 0; i1 < n && ind == 0; i1++) {
    
    		y1 = .0;
    		m1 = i1 + 1;
    		m2 = 0;
    					// ピボット要素の選択
    		for (i2 = i1; i2 < n; i2++) {
    			y2 = fabs(w[i2][i1]);
    			if (y1 < y2) {
    				y1 = y2;
    				m2 = i2;
    			}
    		}
    					// 逆行列が存在しない
    		if (y1 < eps)
    			ind = 1;
    					// 逆行列が存在する
    		else {
    						// 行の入れ替え
    			for (i2 = i1; i2 < nm; i2++) {
    				y1        = w[i1][i2];
    				w[i1][i2] = w[m2][i2];
    				w[m2][i2] = y1;
    			}
    						// 掃き出し操作
    			y1 = 1.0 / w[i1][i1];
    
    			for (i2 = m1; i2 < nm; i2++)
    				w[i1][i2] *= y1;
    
    			for (i2 = 0; i2 < n; i2++) {
    				if (i2 != i1) {
    					for (i3 = m1; i3 < nm; i3++)
    						w[i2][i3] -= w[i2][i1] * w[i1][i3];
    				}
    			}
    		}
    	}
    
    	return(ind);
    }
    			

  2. Java

      アプレット版では,任意のデータに対して,連立方程式の解,逆行列,行列の乗算,及び,行列式の値を画面上で計算することが可能になっています.
    /****************************/
    /* 逆行列の計算             */
    /*      例: 2 1            */
    /*           1 1            */
    /*      coded by Y.Suganuma */
    /****************************/
    import java.io.*;
    
    public class Test {
    	public static void main(String args[]) throws IOException
    	{
    		double w[][], eps;
    		int ind, n = 2, m = 2;
    	/*
    	          データの設定
    	*/
    		w = new double [n][n+m];
    
    		eps     = 1.0e-10;
    		w[0][0] = 2.0;
    		w[0][1] = 1.0;
    		w[0][2] = 1.0;
    		w[0][3] = 0.0;
    		w[1][0] = 1.0;
    		w[1][1] = 1.0;
    		w[1][2] = 0.0;
    		w[1][3] = 1.0;
    	/*
    	          実行と結果
    	*/
    		ind = gauss(w, n, m, eps);
    
    		System.out.println("ind = " + ind);
    		System.out.println("     " + w[0][2] + " " + w[0][3]);
    		System.out.println("     " + w[1][2] + " " + w[1][3]);
    	}
    
    	/*******************************************************/
    	/* 線形連立方程式を解く(逆行列を求める)              */
    	/*      w : 方程式の左辺及び右辺                       */
    	/*      n : 方程式の数                                 */
    	/*      m : 方程式の右辺の列の数                       */
    	/*      eps : 逆行列の存在を判定する規準               */
    	/*      return : =0 : 正常                             */
    	/*               =1 : 逆行列が存在しない               */
    	/*******************************************************/
    	static int gauss(double w[][], int n, int m, double eps)
    	{
    		double y1, y2;
    		int ind = 0, nm, m1, m2, i1, i2, i3;
    
    		nm = n + m;
    
    		for (i1 = 0; i1 < n && ind == 0; i1++) {
    
    			y1 = .0;
    			m1 = i1 + 1;
    			m2 = 0;
    						// ピボット要素の選択
    			for (i2 = i1; i2 < n; i2++) {
    				y2 = Math.abs(w[i2][i1]);
    				if (y1 < y2) {
    					y1 = y2;
    					m2 = i2;
    				}
    			}
    						// 逆行列が存在しない
    			if (y1 < eps)
    				ind = 1;
    						// 逆行列が存在する
    			else {
    							// 行の入れ替え
    				for (i2 = i1; i2 < nm; i2++) {
    					y1        = w[i1][i2];
    					w[i1][i2] = w[m2][i2];
    					w[m2][i2] = y1;
    				}
    							// 掃き出し操作
    				y1 = 1.0 / w[i1][i1];
    
    				for (i2 = m1; i2 < nm; i2++)
    					w[i1][i2] *= y1;
    
    				for (i2 = 0; i2 < n; i2++) {
    					if (i2 != i1) {
    						for (i3 = m1; i3 < nm; i3++)
    							w[i2][i3] -= w[i2][i1] * w[i1][i3];
    					}
    				}
    			}
    		}
    
    		return(ind);
    	}
    }
    			
    アプレット版
    /****************************/
    /* 連立線形方程式と逆行列   */
    /*      coded by Y.Suganuma */
    /****************************/
    import java.awt.*;
    import java.awt.event.*;
    import java.applet.*;
    import java.util.StringTokenizer;
    
    public class Gauss extends Applet implements ActionListener, ItemListener, TextListener {
    	int n = 2, m = 2, l = 2, pr = 0;
    	Choice ch;
    	TextField row, col1, col2;
    	TextArea ta1, ta2, ta3;
    	Label lb1, lb2, lb3;
    	Button bt;
    	Font f = new Font("TimesRoman", Font.BOLD, 20);
    
    	/************/
    	/* 初期設定 */
    	/************/
    	public void init()
    	{
    					// レイアウト,背景色,フォント
    		setLayout(new BorderLayout(5, 5));
    		setBackground(new Color(225, 255, 225));
    		setFont(f);
    					// 上のパネル
    		Panel pn1 = new Panel();
    		add(pn1, BorderLayout.NORTH);
    
    		ch = new Choice ();
    		ch.addItem("連立方程式");
    		ch.addItem("逆行列");
    		ch.addItem("行列の乗算");
    		ch.addItem("行列式");
    		pn1.add(ch);
    		ch.addItemListener(this);
    
    		pn1.add(new Label("行数:"));
    		row = new TextField("2", 2);
    		row.addTextListener(this);
    		pn1.add(row);
    
    		lb1 = new Label("列数1:");
    		lb1.setVisible(false);
    		pn1.add(lb1);
    		col1 = new TextField("2", 2);
    		col1.setVisible(false);
    		col1.addTextListener(this);
    		pn1.add(col1);
    
    		lb2 = new Label("列数2:");
    		lb2.setVisible(false);
    		pn1.add(lb2);
    		col2 = new TextField("2", 2);
    		col2.setVisible(false);
    		col2.addTextListener(this);
    		pn1.add(col2);
    
    		pn1.add(new Label("  "));
    		bt = new Button("OK");
    		bt.setBackground(Color.pink);
    		bt.addActionListener(this);
    		pn1.add(bt);
    					// 中央のパネル(問題)
    		Panel pn2 = new Panel();
    		add(pn2, BorderLayout.CENTER);
    
    		ta1 = new TextArea("2 1\n1 1\n", 10, 20);
    		pn2.add(ta1);
    
    		lb3 = new Label(" X = ");
    		pn2.add(lb3);
    
    		ta2 = new TextArea("1\n1\n", 10, 20);
    		pn2.add(ta2);
    					// 下のパネル(答え)
    		Panel pn3 = new Panel();
    		add(pn3, BorderLayout.SOUTH);
    
    		ta3 = new TextArea(10, 30);
    		pn3.add(ta3);
    	}
    
    	/*****************************************/
    	/* TextFieldの内容が変更されたときの処理 */
    	/*****************************************/
    	public void textValueChanged(TextEvent e)
    	{
    		if (e.getSource() == row) {
    			String str = row.getText();
    			if (str.length() > 0) {
    				n = Integer.parseInt(str);
    				change();
    			}
    		}
    		else if (e.getSource() == col1) {
    			String str = col1.getText();
    			if (str.length() > 0) {
    				m = Integer.parseInt(str);
    				change();
    			}
    		}
    		else {
    			String str = col2.getText();
    			if (str.length() > 0) {
    				l = Integer.parseInt(str);
    				change();
    			}
    		}
    	}
    
    	/************************/
    	/* 選択されたときの処理 */
    	/************************/
    	public void itemStateChanged(ItemEvent e)
    	{
    		if (e.getItemSelectable() == ch) {
    			pr = ch.getSelectedIndex();
    					// 連立方程式,逆行列
    			if (pr == 0 || pr == 1) {
    				lb1.setVisible(false);
    				col1.setVisible(false);
    				lb2.setVisible(false);
    				col2.setVisible(false);
    				lb3.setText(" X = ");
    				lb3.setVisible(true);
    				ta2.setVisible(true);
    			}
    					// 行列の積
    			else if (pr == 2) {
    				lb1.setVisible(true);
    				col1.setVisible(true);
    				lb2.setVisible(true);
    				col2.setVisible(true);
    				lb3.setText("×");
    				lb3.setVisible(true);
    				ta2.setVisible(true);
    			}
    					// 行列式
    			else {
    				lb1.setVisible(false);
    				col1.setVisible(false);
    				lb2.setVisible(false);
    				col2.setVisible(false);
    				lb3.setVisible(false);
    				ta2.setVisible(false);
    			}
    			getParent().validate();
    
    			change();
    		}
    	}
    
    	void change()
    	{
    					// 連立方程式
    		if (pr == 0) {
    			String str;
    			if (n == 2)
    				ta1.setText("2 1\n1 1\n");
    			else {
    				str = "";
    				for (int i1 = 0; i1 < n; i1++) {
    					for (int i2 = 0; i2 < n; i2++) {
    						if (i2 == i1)
    							str += "1 ";
    						else
    							str += "0 ";
    					}
    					str += "\n";
    				}
    				ta1.setText(str);
    			}
    			str = "";
    			for (int i1 = 0; i1 < n; i1++)
    				str += "1\n";
    			ta2.setText(str);
    		}
    					// 逆行列
    		else if (pr == 1) {
    			String str;
    			if (n == 2)
    				ta1.setText("2 1\n1 1\n");
    			else {
    				str = "";
    				for (int i1 = 0; i1 < n; i1++) {
    					for (int i2 = 0; i2 < n; i2++) {
    						if (i2 == i1)
    							str += "1 ";
    						else
    							str += "0 ";
    					}
    					str += "\n";
    				}
    				ta1.setText(str);
    			}
    			str = "";
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 0; i2 < n; i2++) {
    					if (i2 == i1)
    						str += "1 ";
    					else
    						str += "0 ";
    				}
    				str += "\n";
    			}
    			ta2.setText(str);
    		}
    					// 行列の積
    		else if (pr == 2) {
    			String str = "";
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 0; i2 < m; i2++)
    					str += "1 ";
    				str += "\n";
    			}
    			ta1.setText(str);
    			str = "";
    			for (int i1 = 0; i1 < m; i1++) {
    				for (int i2 = 0; i2 < l; i2++)
    					str += "1 ";
    				str += "\n";
    			}
    			ta2.setText(str);
    		}
    					// 行列式
    		else {
    			String str = "";
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 0; i2 < n; i2++) {
    					if (i2 == i1)
    						str += "1 ";
    					else
    						str += "0 ";
    				}
    				str += "\n";
    			}
    			ta1.setText(str);
    		}
    	}
    
    	/******************************/
    	/* ボタンが押されたときの処理 */
    	/******************************/
    	public void actionPerformed(ActionEvent e)
    	{
    					// 連立方程式,逆行列
    		if (pr == 0 || pr == 1) {
    			int m = (pr == 0) ? 1 : n;
    			double w[][] = new double [n][n+m];
    							// 問題の設定
    			String s = ta1.getText();
    			StringTokenizer str = new StringTokenizer(s, " \n");
    			int k = 0;
    			while (str.hasMoreTokens()) {
    				w[k/n][k%n] = Double.parseDouble(str.nextToken());
    				k++;
    			}
    			if (pr == 0) {
    				s   = ta2.getText();
    				str = new StringTokenizer(s, " \n");
    				k   = 0;
    				while (str.hasMoreTokens()) {
    					w[k][n] = Double.parseDouble(str.nextToken());
    					k++;
    				}
    			}
    			else {
    				for (int i1 = 0; i1 < n; i1++) {
    					for (int i2 = 0; i2 < n; i2++) {
    						if (i2 == i1)
    							w[i1][i2+n] = 1;
    						else
    							w[i1][i2+n] = 0;
    					}
    				}
    			}
    							// 計算
    			int sw = gauss(w, n, m, 1.0e-10);
    							// 結果
    			if (sw > 0) {
    				ta3.setForeground(Color.red);
    				ta3.setText(" 解を求めることができません");
    			}
    			else {
    				ta3.setForeground(Color.black);
    				ta3.setText("");
    				for (int i1 = 0; i1 < n; i1++) {
    					for (int i2 = 0; i2 < m; i2++)
    						ta3.append(" " + String.format("%.5f",w[i1][n+i2]));
    					ta3.append("\n");
    				}
    			}
    		}
    					// 行列の積
    		else if (pr == 2) {
    			double A[][] = new double [n][m];
    			double B[][] = new double [m][l];
    			double C[][] = new double [n][l];
    							// 問題の設定
    			String s = ta1.getText();
    			StringTokenizer str = new StringTokenizer(s, " \n");
    			int k = 0;
    			while (str.hasMoreTokens()) {
    				A[k/m][k%m] = Double.parseDouble(str.nextToken());
    				k++;
    			}
    
    			s   = ta2.getText();
    			str = new StringTokenizer(s, " \n");
    			k   = 0;
    			while (str.hasMoreTokens()) {
    				B[k/l][k%l] = Double.parseDouble(str.nextToken());
    				k++;
    			}
    							// 計算
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 0; i2 < l; i2++) {
    					C[i1][i2] = 0.0;
    					for (int i3 = 0; i3 < m; i3++)
    						C[i1][i2] += A[i1][i3] * B[i3][i2];
    				}
    			}
    							// 結果
    			ta3.setForeground(Color.black);
    			ta3.setText("");
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 0; i2 < l; i2++)
    					ta3.append(" " + String.format("%.5f",C[i1][i2]));
    				ta3.append("\n");
    			}
    		}
    					// 行列式
    		else {
    			double A[][] = new double [n][n];
    							// 問題の設定
    			String s = ta1.getText();
    			StringTokenizer str = new StringTokenizer(s, " \n");
    			int k = 0;
    			while (str.hasMoreTokens()) {
    				A[k/n][k%n] = Double.parseDouble(str.nextToken());
    				k++;
    			}
    							// 計算
    			double v = det(n, A);
    							// 結果
    			ta3.setForeground(Color.black);
    			ta3.setText("行列式 = " + String.format("%.5f",v) + "\n");
    		}
    	}
    
    	/******************************************/
    	/* 線形連立方程式を解く(逆行列を求める) */
    	/*      w : 方程式の左辺及び右辺          */
    	/*      n : 方程式の数                    */
    	/*      m : 方程式の右辺の列の数          */
    	/*      eps : 逆行列の存在を判定する規準  */
    	/*      return : =0 : 正常                */
    	/*               =1 : 逆行列が存在しない  */
    	/******************************************/
    	int gauss(double w[][], int n, int m, double eps)
    	{
    		double y1, y2;
    		int ind = 0, nm, m1, m2, i1, i2, i3;
    
    		nm = n + m;
    
    		for (i1 = 0; i1 < n && ind == 0; i1++) {
    
    			y1 = .0;
    			m1 = i1 + 1;
    			m2 = 0;
    						// ピボット要素の選択
    			for (i2 = i1; i2 < n; i2++) {
    				y2 = Math.abs(w[i2][i1]);
    				if (y1 < y2) {
    					y1 = y2;
    					m2 = i2;
    				}
    			}
    						// 逆行列が存在しない
    			if (y1 < eps)
    				ind = 1;
    						// 逆行列が存在する
    			else {
    							// 行の入れ替え
    				for (i2 = i1; i2 < nm; i2++) {
    					y1        = w[i1][i2];
    					w[i1][i2] = w[m2][i2];
    					w[m2][i2] = y1;
    				}
    							// 掃き出し操作
    				y1 = 1.0 / w[i1][i1];
    
    				for (i2 = m1; i2 < nm; i2++)
    					w[i1][i2] *= y1;
    
    				for (i2 = 0; i2 < n; i2++) {
    					if (i2 != i1) {
    						for (i3 = m1; i3 < nm; i3++)
    							w[i2][i3] -= w[i2][i1] * w[i1][i3];
    					}
    				}
    			}
    		}
    
    		return(ind);
    	}
    
    	/************************/
    	/* 行列式の計算        */
    	/*      n : 次数        */
    	/*      A : 行列        */
    	/*      return : 行列式 */
    	/************************/
    	double det(int n, double A[][])
    	{
    		double v = 0.0;
    
    		if (n == 1)
    			v = A[0][0];
    		else if (n == 2)
    			v = A[0][0] * A[1][1] - A[0][1] * A[1][0];
    		else if (n == 3)
    			v = A[0][0] * A[1][1] * A[2][2] + A[1][0] * A[2][1] * A[0][2] + A[0][1] * A[1][2] * A[2][0] - A[2][0] * A[1][1] * A[0][2] - A[0][0] * A[1][2] * A[2][1] - A[0][1] * A[1][0] * A[2][2];
    		else {
    			double B[][] = new double [n-1][n-1];
    			double sgn = 1.0;
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 1; i2 < n; i2++) {
    					for (int i3 = 0; i3 < n; i3++) {
    						if (i3 != i1) {
    							if (i3 < i1)
    								B[i2-1][i3] = A[i2][i3];
    							else
    								B[i2-1][i3-1] = A[i2][i3];
    						}
    					}
    				}
    				v   += sgn * A[0][i1] * det(n-1, B);
    				sgn *= -1.0;
    			}
    		}
    
    		return v;
    	}
    }
    			

  3. JavaScript

      ここをクリックすると,任意のデータに対して,連立方程式の解,逆行列,行列の乗算,及び,行列式の値を画面上で計算することが可能になっています.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>連立線形方程式と逆行列</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<SCRIPT TYPE="text/javascript">
    		method = 0;
    		/**********************************************/
    		/* 連立方程式の解,逆行列,行列の乗算,行列式 */
    		/*      coded by Y.Suganuma                   */
    		/**********************************************/
    		function main()
    		{
    					// 連立方程式の解,逆行列
    			if (method == 0 || method == 1) {
    				let eps = 1.0e-10;
    				let m = parseInt(document.getElementById("row").value);
    				let A = new Array();
    				for (let i1 = 0; i1 < m; i1++)
    					A[i1] = new Array();
    				let s = (document.getElementById("A").value).split(/ {1,}|\n{1,}/);
    				let k = 0;
    				for (let i1 = 0; i1 < m; i1++) {
    					for (let i2 = 0; i2 < m; i2++) {
    						A[i1][i2] = parseFloat(s[k]);
    						k++;
    					}
    				}
    				s = (document.getElementById("B").value).split(/ {1,}|\n{1,}/);
    				k = 0;
    				let n = m + 1;
    				if (method == 1)
    					n = 2 * m;
    				for (let i1 = 0; i1 < m; i1++) {
    					for (let i2 = m; i2 < n; i2++) {
    						A[i1][i2] = parseFloat(s[k]);
    						k++;
    					}
    				}
    
    				let ind = gauss(A, m, n-m, eps);
    
    				if (ind > 0)
    					document.getElementById("C").value = "逆行列が存在しません!";
    				else {
    					let str = "";
    					for (let i1 = 0; i1 < m; i1++) {
    						for (let i2 = m; i2 < n; i2++) {
    							if (i2 == n-1)
    								str = str + A[i1][i2] + "\n";
    							else
    								str = str + A[i1][i2] + " ";
    						}
    					}
    					document.getElementById("C").value = str;
    				}
    			}
    					// 行列の乗算
    			else if (method == 2) {
    				let m = parseInt(document.getElementById("row").value);
    				let n = parseInt(document.getElementById("c1").value);
    				let l = parseInt(document.getElementById("c2").value);
    				let A = new Array();
    				for (let i1 = 0; i1 < m; i1++)
    					A[i1] = new Array();
    				let B = new Array();
    				for (let i1 = 0; i1 < n; i1++)
    					B[i1] = new Array();
    				let C = new Array();
    				for (let i1 = 0; i1 < m; i1++)
    					C[i1] = new Array();
    				let s = (document.getElementById("A").value).split(/ {1,}|\n{1,}/);
    				let k = 0;
    				for (let i1 = 0; i1 < m; i1++) {
    					for (let i2 = 0; i2 < n; i2++) {
    						A[i1][i2] = parseFloat(s[k]);
    						k++;
    					}
    				}
    				s = (document.getElementById("B").value).split(/ {1,}|\n{1,}/);
    				k = 0;
    				for (let i1 = 0; i1 < n; i1++) {
    					for (let i2 = 0; i2 < l; i2++) {
    						B[i1][i2] = parseFloat(s[k]);
    						k++;
    					}
    				}
    
    				for (let i1 = 0; i1 < m; i1++) {
    					for (let i2 = 0; i2 < l; i2++) {
    						C[i1][i2] = 0.0;
    						for (let i3 = 0; i3 < n; i3++)
    							C[i1][i2] += A[i1][i3] * B[i3][i2];
    					}
    				}
    
    				let str = "";
    				for (let i1 = 0; i1 < m; i1++) {
    					for (let i2 = 0; i2 < l; i2++) {
    						if (i2 == l-1)
    							str = str + C[i1][i2] + "\n";
    						else
    							str = str + C[i1][i2] + " ";
    					}
    				}
    				document.getElementById("C").value = str;
    			}
    					// 行列式
    			else {
    				let m = parseInt(document.getElementById("row").value);
    				let A = new Array();
    				for (let i1 = 0; i1 < m; i1++)
    					A[i1] = new Array();
    				let s = (document.getElementById("A").value).split(/ {1,}|\n{1,}/);
    				let k = 0;
    				for (let i1 = 0; i1 < m; i1++) {
    					for (let i2 = 0; i2 < m; i2++) {
    						A[i1][i2] = parseFloat(s[k]);
    						k++;
    					}
    				}
    
    				let v = det(m, A);
    
    				document.getElementById("C").value = v;
    			}
    		}
    
    		/*******************************************************/
    		/* 線形連立方程式を解く(逆行列を求める)              */
    		/*      w : 方程式の左辺及び右辺                       */
    		/*      n : 方程式の数                                 */
    		/*      m : 方程式の右辺の列の数                       */
    		/*      eps : 逆行列の存在を判定する規準               */
    		/*      return : =0 : 正常                             */
    		/*               =1 : 逆行列が存在しない               */
    		/*******************************************************/
    		function gauss(w, n, m, eps)
    		{
    			let nm = n + m;
    			let ind = 0;
    
    			for (let i1 = 0; i1 < n && ind == 0; i1++) {
    
    				let y1 = 0.0;
    				let m1 = i1 + 1;
    				let m2 = 0;
    					// ピボット要素の選択
    				for (let i2 = i1; i2 < n; i2++) {
    					let y2 = Math.abs(w[i2][i1]);
    					if (y1 < y2) {
    						y1 = y2;
    						m2 = i2;
    					}
    				}
    					// 逆行列が存在しない
    				if (y1 < eps)
    					ind = 1;
    					// 逆行列が存在する
    				else {
    						// 行の入れ替え
    					for (let i2 = i1; i2 < nm; i2++) {
    						y1        = w[i1][i2];
    						w[i1][i2] = w[m2][i2];
    						w[m2][i2] = y1;
    					}
    						// 掃き出し操作
    					y1 = 1.0 / w[i1][i1];
    
    					for (let i2 = m1; i2 < nm; i2++)
    						w[i1][i2] *= y1;
    
    					for (let i2 = 0; i2 < n; i2++) {
    						if (i2 != i1) {
    							for (i3 = m1; i3 < nm; i3++)
    								w[i2][i3] -= w[i2][i1] * w[i1][i3];
    						}
    					}
    				}
    			}
    
    			return ind;
    		}
    
    		/************************/
    		/* 行列式の計算        */
    		/*      n : 次数        */
    		/*      A : 行列        */
    		/*      return : 行列式 */
    		/************************/
    		function det(n, A)
    		{
    			let v = 0.0;
    
    			if (n == 1)
    				v = A[0][0];
    			else if (n == 2)
    				v = A[0][0] * A[1][1] - A[0][1] * A[1][0];
    			else if (n == 3)
    				v = A[0][0] * A[1][1] * A[2][2] + A[1][0] * A[2][1] * A[0][2] + A[0][1] * A[1][2] * A[2][0] - A[2][0] * A[1][1] * A[0][2] - A[0][0] * A[1][2] * A[2][1] - A[0][1] * A[1][0] * A[2][2];
    			else {
    				let B = new Array();
    				for (let i1 = 0; i1 < n-1; i1++)
    					B[i1] = new Array();
    				let sgn = 1.0;
    				for (let i1 = 0; i1 < n; i1++) {
    					for (let i2 = 1; i2 < n; i2++) {
    						for (let i3 = 0; i3 < n; i3++) {
    							if (i3 != i1) {
    								if (i3 < i1)
    									B[i2-1][i3] = A[i2][i3];
    								else
    									B[i2-1][i3-1] = A[i2][i3];
    							}
    						}
    					}
    					v   += sgn * A[0][i1] * det(n-1, B);
    					sgn *= -1.0;
    				}
    			}
    
    			return v;
    		}
    
    		/********/
    		/* 目的 */
    		/********/
    		function set_m()
    		{
    			let sel = document.getElementById("method");
    			for (let i1 = 0; i1 < 4; i1++) {
    				if (sel.options[i1].selected) {
    					method = i1;
    					break;
    				}
    			}
    							// 連立方程式
    			if (method == 0) {
    				document.getElementById("row").value = "2";
    				document.getElementById("col1").style.display = "none";
    				document.getElementById("col2").style.display = "none";
    				document.getElementById("op").innerHTML = " x = ";
    				document.getElementById("B").style.display = "";
    				document.getElementById("A").value = "2 1\n1 1";
    				document.getElementById("B").value = "1\n1";
    			}
    							// 逆行列
    			else if (method == 1) {
    				document.getElementById("row").value = "2";
    				document.getElementById("col1").style.display = "none";
    				document.getElementById("col2").style.display = "none";
    				document.getElementById("op").style.display = "";
    				document.getElementById("op").innerHTML = " x = ";
    				document.getElementById("B").style.display = "";
    				document.getElementById("A").value = "2 1\n1 1";
    				document.getElementById("B").value = "1 0\n0 1";
    			}
    							// 行列の乗算
    			else if (method == 2) {
    				document.getElementById("row").value = "2";
    				document.getElementById("c1").value = "2";
    				document.getElementById("c2").value = "2";
    				document.getElementById("col1").style.display = "";
    				document.getElementById("col2").style.display = "";
    				document.getElementById("op").style.display = "";
    				document.getElementById("op").innerHTML = "×";
    				document.getElementById("B").style.display = "";
    				document.getElementById("A").value = "1 1\n1 1";
    				document.getElementById("B").value = "1 1\n1 1";
    			}
    							// 行列式
    			else if (method == 3) {
    				document.getElementById("row").value = "2";
    				document.getElementById("col1").style.display = "none";
    				document.getElementById("col2").style.display = "none";
    				document.getElementById("op").style.display = "none";
    				document.getElementById("B").style.display = "none";
    				document.getElementById("A").value = "1 0\n0 1";
    			}
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY STYLE="font-size: 130%; background-color: #eeffee;">
    
    	<H2 STYLE="text-align:center"><B>連立線形方程式と逆行列</B></H2>
    
    	<DL>
    		<DT>  テキストフィールド及びテキストエリアには,連立方程式の解,逆行列,行列の乗算,及び,行列式の値を計算する例として,以下に示すような場合に対する値が設定されています.他の問題を実行する場合は,それらを適切に修正してください.
    		<P STYLE="text-align:center"><IMG SRC="gauss.gif"></P>
    	</DL>
    
    	<DIV STYLE="text-align:center">
    		目的:<SELECT ID="method" onChange="set_m()" STYLE="font-size:100%">
    			<OPTION SELECTED>連立方程式
    			<OPTION>逆行列
    			<OPTION>行列の乗算
    			<OPTION>行列式
    		</SELECT> 
    		行数:<INPUT ID="row" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="2"> 
    		<SPAN ID="col1" STYLE="display: none"> 列数1:<INPUT ID="c1" STYLE="font-size: 100%;" TYPE="text" SIZE="2" VALUE="2"> </SPAN>
    		<SPAN ID="col2" STYLE="display: none"> 列数2:<INPUT ID="c2" STYLE="font-size: 100%;" TYPE="text" SIZE="2" VALUE="2"> </SPAN>
    		<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">OK</BUTTON><BR><BR>
    		<TEXTAREA ID="A" COLS="20" ROWS="15" STYLE="font-size: 100%">2 1
    1 1</TEXTAREA><SPAN ID="op"> x = </SPAN>
    		<TEXTAREA ID="B" COLS="20" ROWS="15" STYLE="font-size: 100%">1
    1</TEXTAREA><BR><BR>
    		<TEXTAREA ID="C" COLS="30" ROWS="15" STYLE="font-size: 100%"></TEXTAREA>
    	</DIV>
    </BODY>
    
    </HTML>
    			

  4. PHP

    <?php
    
    /****************************/
    /* 逆行列の計算             */
    /*      例: 2 1            */
    /*           1 1            */
    /*      coded by Y.Suganuma */
    /****************************/
    /*
              データの設定
    */
    
    	$eps  = 1.0e-10;
    	$w    = array(2);
    	$w[0] = array(2.0, 1.0, 1.0, 0.0);
    	$w[1] = array(1.0, 1.0, 0.0, 1.0);
    /*
              実行と出力
    */
    	$ind = gauss($w, 2, 2, $eps);
    
    	printf("\$ind = %d\n", $ind);
    	printf("     %f %f\n", $w[0][2], $w[0][3]);
    	printf("     %f %f\n", $w[1][2], $w[1][3]);
    
    /******************************************/
    /* 線形連立方程式を解く(逆行列を求める) */
    /*      $w : 方程式の左辺及び右辺         */
    /*      $n : 方程式の数                   */
    /*      $m : 方程式の右辺の列の数         */
    /*      $eps : 逆行列の存在を判定する規準 */
    /*      return : =0 : 正常                */
    /*               =1 : 逆行列が存在しない  */
    /*******************************************/
    function gauss(&$w, $n, $m, $eps)
    {
    	$ind = 0;
    	$nm  = $n + $m;
    
    	for ($i1 = 0; $i1 < $n && $ind == 0; $i1++) {
    
    		$y1 = 0.0;
    		$m1 = $i1 + 1;
    		$m2 = 0;
    				// ピボット要素の選択
    		for ($i2 = $i1; $i2 < $n; $i2++) {
    			$y2 = abs($w[$i2][$i1]);
    			if ($y1 < $y2) {
    				$y1 = $y2;
    				$m2 = $i2;
    			}
    		}
    				// 逆行列が存在しない
    		if ($y1 < $eps)
    			$ind = 1;
    				// 逆行列が存在する
    		else {
    					// 行の入れ替え
    			for ($i2 = $i1; $i2 < $nm; $i2++) {
    				$y1          = $w[$i1][$i2];
    				$w[$i1][$i2] = $w[$m2][$i2];
    				$w[$m2][$i2] = $y1;
    			}
    					// 掃き出し操作
    			$y1 = 1.0 / $w[$i1][$i1];
    
    			for ($i2 = $m1; $i2 < $nm; $i2++)
    				$w[$i1][$i2] *= $y1;
    
    			for ($i2 = 0; $i2 < $n; $i2++) {
    				if ($i2 != $i1) {
    					for ($i3 = $m1; $i3 < $nm; $i3++)
    						$w[$i2][$i3] -= $w[$i2][$i1] * $w[$i1][$i3];
    				}
    			}
    		}
    	}
    
    	return $ind;
    }
    
    ?>
    			

  5. Ruby

    ############################################
    # 線形連立方程式を解く(逆行列を求める)
    #      w : 方程式の左辺及び右辺
    #      n : 方程式の数
    #      m : 方程式の右辺の列の数
    #      eps : 逆行列の存在を判定する規準
    #      return : =0 : 正常
    #               =1 : 逆行列が存在しない
    #      coded by Y.Suganuma
    ############################################
    
    def gauss(w, n, m, eps)
    
    	nm  = n + m;
    	ind = 0
    
    	for i1 in 0 ... n
    
    		y1 = 0.0
    		m1 = i1 + 1
    		m2 = 0
    					# ピボット要素の選択
    		for i2 in i1 ... n
    			y2 = w[i2][i1].abs()
    			if y1 < y2
    				y1 = y2
    				m2 = i2
    			end
    		end
    					# 逆行列が存在しない
    		if y1 < eps
    			ind = 1
    			break
    					# 逆行列が存在する
    		else   # 行の入れ替え
    			for i2 in i1 ... nm
    				y1        = w[i1][i2]
    				w[i1][i2] = w[m2][i2]
    				w[m2][i2] = y1
    			end
    						# 掃き出し操作
    			y1 = 1.0 / w[i1][i1]
    
    			for i2 in m1 ... nm
    				w[i1][i2] *= y1
    			end
    
    			for i2 in 0 ... n
    				if i2 != i1
    					for i3 in m1 ... nm
    						w[i2][i3] -= (w[i2][i1] * w[i1][i3])
    					end
    				end
    			end
    		end
    	end
    
    	return ind
    end
    
    ############################################
    # 逆行列の計算
    #      例: 2 1
    #           1 1
    #      coded by Y.Suganuma 
    ############################################
    
    			# データの設定
    eps = 1.0e-10
    n   = 2
    m   = 2
    w   = Array[[2.0, 1.0, 1.0, 0.0], [1.0, 1.0, 0.0, 1.0]]
    			# 実行と出力
    ind = gauss(w, n, m, eps)
    
    printf("ind = %d\n", ind)
    printf("     %f %f\n", w[0][2], w[0][3])
    printf("     %f %f\n", w[1][2], w[1][3])
    			

  6. Python

    # -*- coding: UTF-8 -*-
    from math import *
    import numpy as np
    
    ############################################
    # 線形連立方程式を解く(逆行列を求める)
    #      w : 方程式の左辺及び右辺
    #      n : 方程式の数
    #      m : 方程式の右辺の列の数
    #      eps : 逆行列の存在を判定する規準
    #      return : =0 : 正常
    #               =1 : 逆行列が存在しない
    #      coded by Y.Suganuma
    ############################################
    
    def gauss(w, n, m, eps) :
    
    	nm  = n + m
    	ind = 0
    
    	for i1 in range(0, n) :
    
    		y1 = 0.0
    		m1 = i1 + 1
    		m2 = 0
    					# ピボット要素の選択
    		for i2 in range(i1, n) :
    			y2 = abs(w[i2][i1])
    			if y1 < y2 :
    				y1 = y2
    				m2 = i2
    					# 逆行列が存在しない
    		if y1 < eps :
    			ind = 1
    			break
    					# 逆行列が存在する
    		else :   # 行の入れ替え
    			for i2 in range(i1, nm) :
    				y1        = w[i1][i2]
    				w[i1][i2] = w[m2][i2]
    				w[m2][i2] = y1
    						# 掃き出し操作
    			y1 = 1.0 / w[i1][i1]
    
    			for i2 in range(m1, nm) :
    				w[i1][i2] *= y1
    
    			for i2 in range(0, n) :
    				if i2 != i1 :
    					for i3 in range(m1, nm) :
    						w[i2][i3] -= (w[i2][i1] * w[i1][i3])
    
    	return ind
    
    ############################################
    # 逆行列の計算
    #      例: 2 1
    #           1 1
    #      coded by Y.Suganuma 
    ############################################
    
    			# データの設定
    eps = 1.0e-10
    n   = 2
    m   = 2
    w   = np.array([[2, 1, 1, 0], [1, 1, 0, 1]], np.float)
    # w = np.array([[2.0, 1.0, 1.0, 0.0], [1.0, 1.0, 0.0, 1.0]]) でもOK
    # w = np.array([[2, 1, 1, 0], [1, 1, 0, 1]]) はだめ
    # w = [[2, 1, 1, 0], [1, 1, 0, 1]] でもOK
    			# 実行と出力
    ind = gauss(w, n, m, eps)
    
    print("ind = " + str(ind))
    print("     " + str(w[0][2]) + " " + str(w[0][3]))
    print("     " + str(w[1][2]) + " " + str(w[1][3]))
    			

  7. C#

    /****************************/
    /* 逆行列の計算             */
    /*      例: 2 1            */
    /*           1 1            */
    /*      coded by Y.Suganuma */
    /****************************/
    using System;
    
    class Program
    {
    	static void Main()
    	{
    		Test1 ts = new Test1();
    	}
    }
    
    class Test1
    {
    	public Test1()
    	{
    	/*
    	          データの設定
    	*/
    		int n        = 2;
    		int m        = 2;
    		double eps   = 1.0e-10;
    		double[][] w = new double [n][];
    		w[0]         = new double[] {2.0, 1.0, 1.0, 0.0};
    		w[1]         = new double[] {1.0, 1.0, 0.0, 1.0};
    	/*
    	          実行と結果
    	*/
    		int ind = gauss(w, n, m, eps);
    
    		Console.WriteLine("ind = " + ind);
    		Console.WriteLine("     " + w[0][2] + " " + w[0][3]);
    		Console.WriteLine("     " + w[1][2] + " " + w[1][3]);
    	}
    
    	/*******************************************************/
    	/* 線形連立方程式を解く(逆行列を求める)              */
    	/*      w : 方程式の左辺及び右辺                       */
    	/*      n : 方程式の数                                 */
    	/*      m : 方程式の右辺の列の数                       */
    	/*      eps : 逆行列の存在を判定する規準               */
    	/*      return : =0 : 正常                             */
    	/*               =1 : 逆行列が存在しない               */
    	/*******************************************************/
    	int gauss(double[][] w, int n, int m, double eps)
    	{
    		int ind = 0;
    		int nm  = n + m;
    
    		for (int i1 = 0; i1 < n && ind == 0; i1++) {
    
    			double y1 = .0;
    			int m1    = i1 + 1;
    			int m2    = 0;
    						// ピボット要素の選択
    			for (int i2 = i1; i2 < n; i2++) {
    				double y2 = Math.Abs(w[i2][i1]);
    				if (y1 < y2) {
    					y1 = y2;
    					m2 = i2;
    				}
    			}
    						// 逆行列が存在しない
    			if (y1 < eps)
    				ind = 1;
    						// 逆行列が存在する
    			else {
    							// 行の入れ替え
    				for (int i2 = i1; i2 < nm; i2++) {
    					y1        = w[i1][i2];
    					w[i1][i2] = w[m2][i2];
    					w[m2][i2] = y1;
    				}
    							// 掃き出し操作
    				y1 = 1.0 / w[i1][i1];
    
    				for (int i2 = m1; i2 < nm; i2++)
    					w[i1][i2] *= y1;
    
    				for (int i2 = 0; i2 < n; i2++) {
    					if (i2 != i1) {
    						for (int i3 = m1; i3 < nm; i3++)
    							w[i2][i3] -= w[i2][i1] * w[i1][i3];
    					}
    				}
    			}
    		}
    
    		return ind;
    	}
    }
    			

  8. VB

    ''''''''''''''''''''''''''''
    ' 逆行列の計算             '
    '      例: 2 1            '
    '           1 1            '
    '      coded by Y.Suganuma '
    ''''''''''''''''''''''''''''
    Module Test
    
    	Sub Main()
    	'
    	'          データの設定
    	'
    		Dim n As Integer  = 2
    		Dim m As Integer  = 2
    		Dim eps As Double = 1.0e-10
    		Dim w(,) = {{2.0, 1.0, 1.0, 0.0},
    	                {1.0, 1.0, 0.0, 1.0}}
    	'
    	'          実行と結果
    	'
    		Dim ind = gauss(w, n, m, eps)
    
    		Console.WriteLine("ind = " & ind)
    		Console.WriteLine("     " & w(0,2) & " " & w(0,3))
    		Console.WriteLine("     " & w(1,2) & " " & w(1,3))
    
    	End Sub
    
    	''''''''''''''''''''''''''''''''''''''''''
    	' 線形連立方程式を解く(逆行列を求める) '
    	'      w : 方程式の左辺及び右辺          '
    	'      n : 方程式の数                    '
    	'      m : 方程式の右辺の列の数          '
    	'      eps : 逆行列の存在を判定する規準  '
    	'      return : =0 : 正常                '
    	'               =1 : 逆行列が存在しない  '
    	''''''''''''''''''''''''''''''''''''''''''
    	Function gauss(w(,) As Double, n As Integer, m As Integer, eps As Double) As Integer
    
    		Dim ind As Integer = 0
    		Dim nm As Integer  = n + m
    
    		Dim i1 As Integer = 0
    		Do While i1 < n and ind = 0
    
    			Dim y1 As Double  = 0.0
    			Dim m1 As Integer = i1 + 1
    			Dim m2 As Integer = 0
    						' ピボット要素の選択
    			For i2 As Integer = i1 To n-1
    				Dim y2 As Double = Math.Abs(w(i2,i1))
    				If y1 < y2
    					y1 = y2
    					m2 = i2
    				End If
    			Next
    						' 逆行列が存在しない
    			If y1 < eps
    				ind = 1
    						' 逆行列が存在する
    			Else
    							' 行の入れ替え
    				For i2 As Integer = i1 To nm-1
    					y1       = w(i1,i2)
    					w(i1,i2) = w(m2,i2)
    					w(m2,i2) = y1
    				Next
    							' 掃き出し操作
    				y1 = 1.0 / w(i1,i1)
    
    				For i2 As Integer = m1 To nm-1
    					w(i1,i2) *= y1
    				Next
    
    				For i2 As Integer = 0 To n-1
    					If i2 <> i1
    						For i3 As Integer = m1 To nm-1
    							w(i2,i3) -= w(i2,i1) * w(i1,i3)
    						Next
    					End If
    				Next
    			End If
    			i1 += 1
    		Loop
    
    		Return ind
    
    	End Function
    
    End Module
    			

静岡理工科大学 菅沼ホーム 目次 索引