克莱姆法则:前提,方程的个数与未知数数量一致
将所有的系数作为一个行列式,如果解不为零,则方程有唯一解,其次方程无解
将结果替换掉第一列作为一个行列式,求解,将这个解除以系数行列式的解的结果为第一个未知数的解
将结果替换掉第二列作为一个行列式,求解,将这个解除以系数行列式的解的结果为第一个未知数的解
。。。。。。
package com.example.equation.service.impl;import com.example.equation.service.SolveService;import org.springframework.stereotype.Service;import org.springframework.util.StringUtils;import java.io.BufferedReader;import java.io.File;import java.io.IOException;import java.math.BigDecimal;import java.math.RoundingMode;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;@Servicepublic class SolveServiceImpl implements SolveService {/*a + b + c = 15a + b + d = 18a + c + d = 16b + c + d = 17*/@Overridepublic void solve() throws Exception {/*BigDecimal[][] arr = {{new BigDecimal(1), new BigDecimal(1), new BigDecimal(1), new BigDecimal(0), new BigDecimal(15)},{new BigDecimal(1), new BigDecimal(1), new BigDecimal(0), new BigDecimal(1), new BigDecimal(18)},{new BigDecimal(1), new BigDecimal(0), new BigDecimal(1), new BigDecimal(1), new BigDecimal(16)},{new BigDecimal(0), new BigDecimal(1), new BigDecimal(1), new BigDecimal(1), new BigDecimal(17)}};*/BigDecimal[][] arr = readFile("D:/x.txt");/*int[][] d = {{arr[0][0], arr[0][1], arr[0][2]},{arr[1][0], arr[1][1], arr[1][2]},{arr[2][0], arr[2][1], arr[2][2]}};int[][] d1 = {{arr[0][3], arr[0][1], arr[0][2]},{arr[1][3], arr[1][1], arr[1][2]},{arr[2][3], arr[2][1], arr[2][2]}};int[][] d2 = {{arr[0][0], arr[0][3], arr[0][2]},{arr[1][0], arr[1][3], arr[1][2]},{arr[2][0], arr[2][3], arr[2][2]}};int[][] d3 = {{arr[0][0], arr[0][1], arr[0][3]},{arr[1][0], arr[1][1], arr[1][3]},{arr[2][0], arr[2][1], arr[2][3]}};*/System.out.println("----------------");List<BigDecimal[][]> determinant = new ArrayList<>(arr.length + 1);for (int i = 0; i < arr.length + 1; i++) {System.out.println("第" + i + "个行列式:");BigDecimal[][] d = new BigDecimal[arr.length][arr.length];for (int row = 0; row < d.length; row++) {for (int col = 0; col < d.length; col++) {if (i == 0) {d[row][col] = arr[row][col];} else {if (col == i - 1) {d[row][col] = arr[row][arr.length];} else {d[row][col] = arr[row][col];}}}}determinant.add(d);System.out.println(Arrays.deepToString(d));}/*int D = determinant(d);int D1 = determinant(d1);int D2 = determinant(d2);int D3 = determinant(d3);System.out.println("D=" + D + ",D1=" + D1 + ",D2=" + D2 + ",D3=" + D3);*/System.out.println("----------------");System.out.println("行列式的解:");List<BigDecimal> D = new ArrayList<>();for (int i = 0; i < determinant.size(); i++) {BigDecimal det = det(determinant.get(i));if (det.compareTo(BigDecimal.ZERO) == 0 && i == 0) {throw new Exception("方程无解");}D.add(det);}System.out.println(D);/*int x = D1 / D;int y = D2 / D;int z = D3 / D;System.out.println("x=" + x + ",y=" + y + ",z=" + z);*/System.out.println("----------------");System.out.println("方程的解:");List<BigDecimal> result = new ArrayList<>();for (int i = 1; i < D.size(); i++) {result.add(D.get(i).divide(D.get(0), 4, RoundingMode.HALF_UP));}System.out.println(result);}/*** 行列式的解*/private BigDecimal detResult;/*** 求一个行列式的解,例如* (d[0][0] * d[1][1] * d[2][2]) + (d[0][1] * d[1][2] * d[2][0]) + (d[0][2] * d[1][0] * d[2][1])* - (d[0][0] * d[1][2] * d[2][1]) - (d[0][1] * d[1][0] * d[2][2]) - (d[0][2] * d[1][1] * d[2][0]);** @param d 行列式数组* @return 行列式的解*/private BigDecimal det(BigDecimal[][] d) {// 初始化结果detResult = BigDecimal.ZERO;// 初始化路径int[] path = new int[d.length];Arrays.fill(path, -1);// 从0行0列开始遍历// System.out.println("行列式的路径:");return detRecursion(d, 0, path, BigDecimal.ONE);}/*** 递归求行列式的解** @param d 行列式数组* @param row 当前行数* @param path 递归路径,保存的key是行数,value是列数,保证每行不在同一列上* @param multiplyResult 保存的是当前所递归路径的乘积* @return 行列式的解*/private BigDecimal detRecursion(BigDecimal[][] d, int row, int[] path, BigDecimal multiplyResult) {int length = d.length;// 当行数大于总行数,说明递归到最底层了if (row >= length) {multiplyResult = multiplyResult.multiply(new BigDecimal(inversionNumber(path) % 2 == 0 ? 1 : -1));// System.out.println("路径:"+ Arrays.toString(path)+ ",结果:"+multiplyResult);detResult = detResult.add(multiplyResult);return detResult;}// 对每一列进行遍历,确保每一种组合都能遍历到for (int col = 0; col < length; col++) {// 对路径进行遍历,如果当前列与之前的列在同一列,则换下一列boolean flag = false;for (int i : path) {if (i == col) {flag = true;break;}}if (!flag) {// 如果当前列可用,将列放到路径中path[row] = col;// 进行下一行递归detRecursion(d, row + 1, path, d[row][col].multiply(multiplyResult));// 还原路径path[row] = -1;}}return detResult;}/*** 计算逆序数 e.g. 1,2,4,3 逆序数个数是 1 1,2,3,4 逆序数个数是 0** @param arr 数组* @return 逆序数个数*/private int inversionNumber(int[] arr) {int count = 0;for (int i = 0; i < arr.length; i++) {for (int j = i + 1; j < arr.length; j++) {if (arr[i] > arr[j]) {count++;}}}return count;}/*** 读取文件中的*/private BigDecimal[][] readFile(String filepath) throws IOException {File file = new File(filepath);BigDecimal[][] arr;try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {List<String> lines = reader.lines().collect(Collectors.toList());arr = new BigDecimal[lines.size()][];for (int i = 0; i < lines.size(); i++) {String line = lines.get(i).trim();if (!StringUtils.isEmpty(line)) {String[] arrStr = line.split("[,,]");arr[i] = new BigDecimal[arrStr.length];for (int j = 0; j < arrStr.length; j++) {arr[i][j] = new BigDecimal(arrStr[j].trim());}}}}System.out.println(Arrays.deepToString(arr));return arr;}}
文本内容:
2, 3, 1, 61, -1, 2, -11, 2, -1, 5
输出:
[[2, 3, 1, 6], [1, -1, 2, -1], [1, 2, -1, 5]]----------------第0个行列式:[[2, 3, 1], [1, -1, 2], [1, 2, -1]]第1个行列式:[[6, 3, 1], [-1, -1, 2], [5, 2, -1]]第2个行列式:[[2, 6, 1], [1, -1, 2], [1, 5, -1]]第3个行列式:[[2, 3, 6], [1, -1, -1], [1, 2, 5]]----------------行列式的解:[6, 12, 6, -6]----------------方程的解:[2, 1, -1]
