【Java】連立方程式を解く_Ver1
今回は連立方程式の解を求める問題です。
コード更新しています。解説等はこのままこの記事で解説していますので、解説等読んだ後はVer2のコードを参照してください。
連立方程式は手で書きながらやる分には全然簡単なのですが、いざプログラムでやろうとすると、、、?とりあえず、xとyをイコールで求められる式まで落とし込むことにしました。
1.ax + by = c
by = c - ax
y = (c - ax) / b
2.dx + ey = f
dx + e((c-ax) / b) = f
dx + ce / b - aex / b = f
(bd - ae)x = f - ce /b
x = (bf - ce) / (bd - ae)
上記の式を利用して解を求めます。
import static java.lang.System.out;
import static java.lang.Double.parseDouble;
import java.io.File;
import java.util.Scanner;
public class SimultaneousEquation {
public static void main(String[] args) {
new SimultaneousEquation().simul();
}
public void simul() {
try (Scanner scan = new Scanner(System.in)) {
simulEqua(scan);
} catch (Exception e) {
}
}
public void simul(String inDataPath) {
try (Scanner scan = new Scanner(new File(inDataPath))) {
simulEqua(scan);
} catch (Exception e) {
}
}
public void simulEqua(Scanner scan) {
String inData;
while ((inData = scan.nextLine()) != null || !"".equals(inData)) {
String[] abcdefList = inData.split(" ");
double[] in = new double[6];
for (int i = 0; i < 6; i++) {
in[i] = parseDouble(abcdefList[i]);
}
double[] xy = getXY(in);
out.printf("%4.3f %4.3f\n", xy[0], xy[1]);
}
}
public double[] getXY(double[] in) {
double[] xy = new double[2];
xy[0] = (in[1] * in[5] - in[2] * in[4]) / (in[1] * in[3] - in[0] * in[4]);
xy[0] = judge(xy[0]);
xy[1] = (in[2] - in[0] * xy[0]) / in[1];
xy[1] = judge(xy[1]);
return xy;
}
public double judge(double num) {
return (num == -0.0) ? 0.0 : num;
}
}
getXYというメソッドで式を利用しています。久しぶりに数式をいじったので、解くのにかなり時間がかかりました。配列を使用しているため、どこがaでどこがbかが分かりづらいですが、一応abcdefの順番に入れています。より分かりやすく記載できる方法があればコメントお願いいたします。
テストドライバは以下になります。
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import volume0.BaseTest;
public class SimultaneousEquationTest extends BaseTest {
private SimultaneousEquation se;
@Before
public void setUp() throws Exception {
super.setUp();
se = new SimultaneousEquation();
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
@Test
public void testSimul0001() {
try {
se.simul("./data/volume0_0004/0001/in.txt");
outList = outContent.toString().split("\n");
assertOut(outList, "./data/volume0_0004/0001/out.txt");
} catch (Exception e) {
printErr(e);
}
}
@Test
public void testSimul0002() {
try {
se.simul("./data/volume0_0004/0002/in.txt");
outList = outContent.toString().split("\n");
assertOut(outList, "./data/volume0_0004/0002/out.txt");
} catch (Exception e) {
printErr(e);
}
}
}
テストドライバの「in.txt」「out.txt」は以下になります。
0001/in.txt
1 2 3 4 5 6
2 -1 -2 -1 -1 -5
0001/out.txt
-1.000 2.000
1.000 4.000
0002/in.txt
2 -1 -3 1 -1 -3
2 -1 -3 -9 9 27
0002/out.txt
0.000 3.000
0.000 3.000
今回の問題は、以下にあります。
アルゴリスムで困った時は、以下の本を参考にしてます。Javaに置き換えるのが少々難解ですが、、、
テストドライバで継承しているクラスは以下の記事に記載しています。参考にしてみてください。