質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

1942閲覧

java ガウスの消去法

hanao_

総合スコア6

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/12/02 10:27

編集2021/12/02 12:04

Javaで、ガウスの消去法を行うプログラムを書いているのですが、答えが違ってしまいます、、、どこが間違っているのでしょうか?

augMatrix.matrixはArrayList<ArrayList<Double>>型で、拡大係数行列で、

2.0 4.0 -2.0 -4.0 -10.0
-6.0 -12.0 12.0 24.0 60.0
4.0 2.0 2.0 -4.0 8.0
2.0 -4.0 -2.0 4.0 6.0

の行列が入っています

ans.vectorはArrayList<Double>型で、解を格納するものです。

今のプログラムでは、解が

10.0 -5.0 -5.0 2.5

となってしまうのですが、正しい解は

2.0 -1.0 3.0 1.0

です。

わかりずらいプログラムだと思いますが、よろしくお願いします。

Java

1Vector solve() { 2 3 Vector ans = new Vector(); 4 ArrayList<ArrayList<Double>> b = new ArrayList<ArrayList<Double>>(); 5 //行列の行数 6 int N=augMatrix.matrix.size(); 7 int pivot; 8 double p,q,m; 9 10 //初期化 11 for(int i=0;i<1;i++) { 12 ArrayList<Double> t = new ArrayList<Double>(); 13 for(int j=0;j<N+1;j++) { 14 t.add(j,0.0); 15 } 16 b.add(t); 17 } 18 19 //初期化 20 for(int i=0;i<N;i++) { 21 ans.vector.add(0.0); 22 } 23 24 for(int i=0;i<N;i++){ 25 m=0; 26 pivot=i; 27 28 for(int l=i;l<N;l++) { 29 if(Math.abs(augMatrix.matrix.get(l).get(i))>m) { 30 //i列の中で一番値が大きい行を選ぶ 31 m=Math.abs(augMatrix.matrix.get(l).get(i)); 32 pivot=l; 33 } 34 } 35 36 if(pivot!=i) { 37 38 //pivotがiと違えば、行の入れ替え 39 for(int j=0;j<N+1;j++) { 40 41 b.get(0).set(j,augMatrix.matrix.get(i).get(j)); 42 augMatrix.matrix.get(i).set(j,augMatrix.matrix.get(pivot).get(j)); 43 augMatrix.matrix.get(pivot).set(j,b.get(0).get(j)); 44 } 45 } 46 } 47 48 for(int k=0;k<N;k++) { 49 //対角要素を保存 50 p=augMatrix.matrix.get(k).get(k); 51 //対角要素は1になることがわかっているから 52 augMatrix.matrix.get(k).set(k,1.0); 53 54 for(int j=k+1;j<N+1;j++) { 55 augMatrix.matrix.get(k).set(j,(augMatrix.matrix.get(k).get(j))/p); 56 } 57 58 for(int i=k+1;i<N;i++) { 59 q=augMatrix.matrix.get(i).get(k); 60 for(int j=k+1;j<N+1;j++) { 61 augMatrix.matrix.get(i).set(j,-q*(augMatrix.matrix.get(k).get(j))); 62 } 63 //0となることがわかっているところ 64 augMatrix.matrix.get(i).set(k,0.0); 65 } 66 } 67 68 //解の計算 69 for(int i=N-1;i>=0;i--) { 70 ans.vector.set(i,(augMatrix.matrix.get(i).get(N))); 71 for(int j=N-1;j>i;j--) { 72 ans.vector.set(i,-1*(augMatrix.matrix.get(i).get(j))*ans.vector.get(j)); 73 } 74 } 75 76 //最終的な行列の表示 77 result1(augMatrix.matrix); 78 79 //解の出力 80 result2(ans.vector); 81 82 return ans; 83 }

Java

1void result1(ArrayList<ArrayList<Double>> matrix) { 2 for(int i=0;i<matrix.size();i++) { 3 for(int j=0;j<matrix.get(0).size();j++) { 4 System.out.print(matrix.get(i).get(j)+" "); 5 } 6 System.out.println(""); 7 } 8}

Java

1void result2(ArrayList<Double> vector) { 2 System.out.println("解は"); 3 for(int i=0;i<vector.size();i++) { 4 System.out.println(vector.get(i)); 5 } 6}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/12/02 10:54 編集

どのような値を入れてどのような答えになったのでしょうか。 teratail はデバッグを依頼する場所では無いと思います。 公式に公開されている各クラスやメソッドが仕様通りに動作していないのならともかく、ご自身で書いたプログラムのデバッグをまずご自身で行っていなければ、依頼と思われます。 プログラムの進行とともに変化する各変数の値の遷移をどこまで調査し、何がどう分からずにご質問に至ったのでしょうか。 「わかりずらいプログラムだと思」われるのでしたら、分かり易くなるよう修正されては如何でしょう。 インデントを整えるだけでもかなり見栄えは違うと思いますが。 (タブとスペースの混在でインデントを付けていると teratail では崩れやすいですので、どちらかに統一されると良いかと思います。) また、ローカル変数をメソッドの最初で定義する書式は、ローカル変数のスコープを最大にし、(一定以上長いメソッドの場合は特に)変数値の追跡をむやみに難しくさせます。 augMatrix.matrix のような広域な変数の使用を見直すのと同様、処理単位毎にメソッドを分ける等して各変数のスコープをなるべく狭くすることも、分かり易いプログラムにするコツのように思います。
hanao_

2021/12/02 12:02

すみませんでした、、、自分なりにコードを編集してみました。 変数のスコープについては今まで意識したことがなかったので、これから気を付けたいと思います。 勉強になります。
guest

回答3

0

diff

1+ dump 2 for(int k=0;k<N;k++) { 3 //対角要素を保存 4 p=augMatrix.matrix.get(k).get(k); 5 //対角要素は1になることがわかっているから 6 augMatrix.matrix.get(k).set(k,1.0); 7 8 for(int j=k+1;j<N+1;j++) { 9 augMatrix.matrix.get(k).set(j,(augMatrix.matrix.get(k).get(j))/p); 10 } 11+ dump 12 13 for(int i=k+1;i<N;i++) { 14 q=augMatrix.matrix.get(i).get(k); 15 for(int j=k+1;j<N+1;j++) { 16 augMatrix.matrix.get(i).set(j,-q*(augMatrix.matrix.get(k).get(j))); 17 } 18 //0となることがわかっているところ 19 augMatrix.matrix.get(i).set(k,0.0); 20 } 21+ dump 22 }

上記3か所にダンプ用コードを入れて実行し、配列の中身を出力した結果か以下になります。

text

1---dump data start--- 2[-6.0, -12.0, 12.0, 24.0, 60.0] 3[2.0, 4.0, -2.0, -4.0, -10.0] 4[4.0, 2.0, 2.0, -4.0, 8.0] 5[2.0, -4.0, -2.0, 4.0, 6.0] 6---dump data end--- 7---dump data start--- 8[1.0, 2.0, -2.0, -4.0, -10.0] 9[2.0, 4.0, -2.0, -4.0, -10.0] 10[4.0, 2.0, 2.0, -4.0, 8.0] 11[2.0, -4.0, -2.0, 4.0, 6.0] 12---dump data end--- 13---dump data start--- 14[1.0, 2.0, -2.0, -4.0, -10.0] 15[0.0, -4.0, 4.0, 8.0, 20.0] 16[0.0, -8.0, 8.0, 16.0, 40.0] 17[0.0, -4.0, 4.0, 8.0, 20.0] 18---dump data end--- 19---dump data start--- 20[1.0, 2.0, -2.0, -4.0, -10.0] 21[0.0, 1.0, -1.0, -2.0, -5.0] 22[0.0, -8.0, 8.0, 16.0, 40.0] 23[0.0, -4.0, 4.0, 8.0, 20.0] 24---dump data end--- 25---dump data start--- 26[1.0, 2.0, -2.0, -4.0, -10.0] 27[0.0, 1.0, -1.0, -2.0, -5.0] 28[0.0, 0.0, -8.0, -16.0, -40.0] 29[0.0, 0.0, -4.0, -8.0, -20.0] 30---dump data end--- 31---dump data start--- 32[1.0, 2.0, -2.0, -4.0, -10.0] 33[0.0, 1.0, -1.0, -2.0, -5.0] 34[0.0, 0.0, 1.0, 2.0, 5.0] 35[0.0, 0.0, -4.0, -8.0, -20.0] 36---dump data end--- 37---dump data start--- 38[1.0, 2.0, -2.0, -4.0, -10.0] 39[0.0, 1.0, -1.0, -2.0, -5.0] 40[0.0, 0.0, 1.0, 2.0, 5.0] 41[0.0, 0.0, 0.0, 8.0, 20.0] 42---dump data end--- 43---dump data start--- 44[1.0, 2.0, -2.0, -4.0, -10.0] 45[0.0, 1.0, -1.0, -2.0, -5.0] 46[0.0, 0.0, 1.0, 2.0, 5.0] 47[0.0, 0.0, 0.0, 1.0, 2.5] 48---dump data end--- 49---dump data start--- 50[1.0, 2.0, -2.0, -4.0, -10.0] 51[0.0, 1.0, -1.0, -2.0, -5.0] 52[0.0, 0.0, 1.0, 2.0, 5.0] 53[0.0, 0.0, 0.0, 1.0, 2.5] 54---dump data end--- 55---dump data start--- 56[1.0, 2.0, -2.0, -4.0, -10.0] 57[0.0, 1.0, -1.0, -2.0, -5.0] 58[0.0, 0.0, 1.0, 2.0, 5.0] 59[0.0, 0.0, 0.0, 1.0, 2.5] 60---dump data end---

正しく消去法ができていると思いますか?

投稿2021/12/03 19:35

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

argMatrix.matrix がコード中にたくさんあって見にくいいので、
solve() の先頭で、変数 m にしています。

java

1import java.util.ArrayList; 2import java.util.Arrays; 3 4class Matrix { 5 ArrayList<ArrayList<Double>> matrix; 6 7 Matrix(Double[][] d) { 8 matrix = new ArrayList<>(); 9 for (var e : d) 10 matrix.add(new ArrayList<Double>(Arrays.asList(e))); 11 } 12} 13 14class Gauss { 15 Double[][] d = { 16 { 2.0, 4.0, -2.0, -4.0, -10.0 }, 17 { -6.0, -12.0, 12.0, 24.0, 60.0 }, 18 { 4.0, 2.0, 2.0, -4.0, 8.0 }, 19 { 2.0, -4.0, -2.0, 4.0, 6.0 }, 20 }; 21 Matrix augMatrix = new Matrix(d); 22 int N = augMatrix.matrix.size(); 23 24 ArrayList<Double> solve() { 25 ArrayList<ArrayList<Double>> m = augMatrix.matrix; 26 for (int k = 0; k < N; k++) { 27 double t = Math.abs(m.get(k).get(k)); 28 int p = k; 29 for (int i = k+1; i < N; i++) 30 if (m.get(i).get(k) > t) { 31 t = Math.abs(m.get(i).get(k)); 32 p = i; 33 } 34 if (p != k) 35 for (int j = 0; j <= N; j++) { 36 t = m.get(k).get(j); 37 m.get(k).set(j, m.get(p).get(j)); 38 m.get(p).set(j, t); 39 } 40 for (int i = k+1; i < N; i++) { 41 t = m.get(i).get(k) / m.get(k).get(k); 42 for (int j = k; j <= N; j++) 43 m.get(i).set(j, m.get(i).get(j) - t * m.get(k).get(j)); 44 } 45 } 46 47 for (int k = N; --k > 0; ) 48 for (int i = k; --i >= 0; ) { 49 double t = m.get(i).get(k) / m.get(k).get(k); 50 for (int j = 0; j <= N; j++) 51 m.get(i).set(j, m.get(i).get(j) - t * m.get(k).get(j)); 52 } 53 54 for (int k = 0; k < N; k++) { 55 m.get(k).set(N, m.get(k).get(N) / m.get(k).get(k)); 56 m.get(k).set(k, 1.0); 57 } 58 59 result1(m); 60 61 ArrayList<Double> vector = new ArrayList<>(); 62 for (int i = 0; i < N; i++) 63 vector.add(m.get(i).get(N)); 64 return vector; 65 } 66 67 void result1(ArrayList<ArrayList<Double>> matrix) { 68 for (int i = 0; i < matrix.size(); i++) { 69 for (int j = 0; j < matrix.get(0).size(); j++) 70 System.out.printf("%8.3f", matrix.get(i).get(j)); 71 System.out.println(); 72 } 73 } 74} 75 76class Main { 77 public static void main(String[] args) { 78 ArrayList<Double> ans = new Gauss().solve(); 79 System.out.println(); 80 for (var e : ans) System.out.printf("%8.3f", e); 81 System.out.println(); 82 } 83}

実行結果

text

1 1.000 0.000 0.000 0.000 2.000 2 0.000 1.000 0.000 0.000 -1.000 3 0.000 0.000 1.000 0.000 3.000 4 0.000 0.000 0.000 1.000 1.000 5 6 2.000 -1.000 3.000 1.000

追記
上記のコードに間違いがありました。

if (m.get(i).get(k) > t) {
if (Math.abs(m.get(i).get(k)) > t) { に修正してください。

今回のデータでは、たまたま結果が正しくなっていました。

追記2

java

1 if (p != k) 2 for (int j = 0; j <= N; j++) { 3 t = m.get(k).get(j); 4 m.get(k).set(j, m.get(p).get(j)); 5 m.get(p).set(j, t); 6 }

これは、if (p != k) java.util.Collections.swap(m, k, p); と書き換え可能です。

投稿2021/12/03 06:22

編集2021/12/04 10:27
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

二重コレクション(List<List<Double>>)は扱い難いので、クラスとしてまとめる形で配列に戻し(?)てみました。
division 等でコメントにしてある println や printMatrix を有効にすれば動作が確認し易いかと思いますので、ご自身のコードでも同じように表示してみると違う個所が分かるかと思います。

java

1package teratail_java.q371994; 2 3import java.io.PrintStream; 4 5public class Q371994 { 6 7 public static void main(String[] args) { 8/* 9 GaussianEliminationMatrix matrix = new GaussianEliminationMatrix( 10 new double[] { 11 2, 4,-2, 8, //2[x1]+4[x2]-2[x3]=8 12 1, 2, 1, 6, // [x1]+2[x2]+ [x3]=6 13 1, 3, 2, 9, // [x1]+3[x2]+2[x3]=9 14 }); 15*/ 16 GaussianEliminationMatrix matrix = new GaussianEliminationMatrix( 17 new double[] { 18 2.0, 4.0,-2.0,-4.0, -10.0, 19 -6.0,-12.0,12.0,24.0, 60.0, 20 4.0, 2.0, 2.0,-4.0, 8.0, 21 2.0, -4.0,-2.0, 4.0, 6.0, 22 }); 23 matrix.printMatrix("start ---"); 24 25 matrix.forwardElimination(); 26 matrix.printMatrix("forward ---"); 27 28 double[] x = matrix.backwardSubstitution(); 29 30 System.out.println("解は"); 31 for(int i=0; i<x.length; i++) { 32 System.out.println(x[i]); 33 } 34 35 //Vector<Double> ans = new Vector<Double>(x.length); 36 //for(Double b : x) ans.add(b); 37 //return ans; 38 } 39} 40 41final class GaussianEliminationMatrix { 42 private int size; 43 private double[][] a_b; 44 45 GaussianEliminationMatrix(double[] matrix) { 46 size = (int)(Math.sqrt(matrix.length)); 47 if(matrix.length != size*size+size) throw new IllegalArgumentException(); 48 49 int w = size + 1; 50 a_b = new double[size][w]; 51 for(int i=0; i<matrix.length; i++) { 52 a_b[i/w][i%w] = matrix[i]; 53 } 54 } 55 56 double getA(int i, int j) { 57 if(j >= size) throw new ArrayIndexOutOfBoundsException("j"); 58 return a_b[i][j]; 59 } 60 double getB(int i) { return a_b[i][size]; } 61 62 //前進消去 63 void forwardElimination() { 64 for(int k=0; k<size-1; k++) { 65 int p = pivoting(k); 66 swap(k, p); 67 division(k); 68 for(int i=k+1; i<size; i++) { 69 subtraction(k, i); 70 } 71 } 72 } 73 //k行k列から下の中で一番絶対値が大きい行 74 private int pivoting(int k) { 75 int pivot = 0; 76 double m = 0; 77 for(int l=k; l<size; l++) { 78 if(m < Math.abs(getA(l,k))) { 79 m = Math.abs(getA(l,k)); 80 pivot = l; 81 } 82 } 83 return pivot; 84 } 85 //行の入れ替え 86 private void swap(int k, int p) { 87 double t; 88 for(int i=0; i<size+1; i++) { 89 t = a_b[k][i]; 90 a_b[k][i] = a_b[p][i]; 91 a_b[p][i] = t; 92 } 93 //System.out.println("swap: k="+k+", p="+p); 94 //printMatrix("swap"); 95 } 96 //行の徐算(k行k列を1にする) 97 private void division(int k) { 98 double q = getA(k,k); 99 //System.out.println("division: k="+k+", q="+q); 100 for(int l=k; l<size+1; l++) { 101 a_b[k][l] /= q; 102 } 103 //printMatrix("division"); 104 } 105 //行の減算(i行k列を0にする) 106 private void subtraction(int k, int i) { 107 double p = getA(i,k) / getA(k,k); 108 //System.out.println("subtraction: k="+k+", i="+i+", p="+p); 109 for(int l=k; l<size+1; l++) { 110 a_b[i][l] -= p * a_b[k][l]; 111 } 112 //printMatrix("subtraction"); 113 } 114 115 //後退代入 116 double[] backwardSubstitution() { 117 double[] x = new double[size]; 118 119 x[size-1] = getB(size-1) / getA(size-1,size-1); 120 for(int i=size-2; i>=0; i--) { 121 double s=0; 122 for(int j=i+1; j<size; j++) { 123 s += getA(i,j) * x[j]; 124 } 125 x[i] = (getB(i) - s) / getA(i,i); 126 } 127 128 return x; 129 } 130 131 //表示 132 void printMatrix(String header) { 133 System.out.println(header); 134 printMatrix(System.out); 135 } 136 void printMatrix(PrintStream out) { 137 for(int i=0; i<size; i++) { 138 for(int j=0; j<size+1; j++) { 139 System.out.print(a_b[i][j] + " "); 140 } 141 System.out.println(); 142 } 143 } 144}

実行結果

plain

1start --- 22.0 4.0 -2.0 -4.0 -10.0 3-6.0 -12.0 12.0 24.0 60.0 44.0 2.0 2.0 -4.0 8.0 52.0 -4.0 -2.0 4.0 6.0 6forward --- 71.0 2.0 -2.0 -4.0 -10.0 80.0 1.0 -0.25 -1.5 -3.25 90.0 0.0 1.0 0.35294117647058826 3.3529411764705883 100.0 0.0 0.0 3.2941176470588234 3.2941176470588234 11解は 122.0 13-1.0 143.0 151.0

投稿2021/12/02 19:35

jimbe

総合スコア12756

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問