克莱姆法则:前提,方程的个数与未知数数量一致
    将所有的系数作为一个行列式,如果解不为零,则方程有唯一解,其次方程无解
    将结果替换掉第一列作为一个行列式,求解,将这个解除以系数行列式的解的结果为第一个未知数的解
    将结果替换掉第二列作为一个行列式,求解,将这个解除以系数行列式的解的结果为第一个未知数的解
    。。。。。。

    1. package com.example.equation.service.impl;
    2. import com.example.equation.service.SolveService;
    3. import org.springframework.stereotype.Service;
    4. import org.springframework.util.StringUtils;
    5. import java.io.BufferedReader;
    6. import java.io.File;
    7. import java.io.IOException;
    8. import java.math.BigDecimal;
    9. import java.math.RoundingMode;
    10. import java.nio.charset.StandardCharsets;
    11. import java.nio.file.Files;
    12. import java.util.ArrayList;
    13. import java.util.Arrays;
    14. import java.util.List;
    15. import java.util.stream.Collectors;
    16. @Service
    17. public class SolveServiceImpl implements SolveService {
    18. /*
    19. a + b + c = 15
    20. a + b + d = 18
    21. a + c + d = 16
    22. b + c + d = 17
    23. */
    24. @Override
    25. public void solve() throws Exception {
    26. /*
    27. BigDecimal[][] arr = {
    28. {new BigDecimal(1), new BigDecimal(1), new BigDecimal(1), new BigDecimal(0), new BigDecimal(15)},
    29. {new BigDecimal(1), new BigDecimal(1), new BigDecimal(0), new BigDecimal(1), new BigDecimal(18)},
    30. {new BigDecimal(1), new BigDecimal(0), new BigDecimal(1), new BigDecimal(1), new BigDecimal(16)},
    31. {new BigDecimal(0), new BigDecimal(1), new BigDecimal(1), new BigDecimal(1), new BigDecimal(17)}
    32. };
    33. */
    34. BigDecimal[][] arr = readFile("D:/x.txt");
    35. /*
    36. int[][] d = {
    37. {arr[0][0], arr[0][1], arr[0][2]},
    38. {arr[1][0], arr[1][1], arr[1][2]},
    39. {arr[2][0], arr[2][1], arr[2][2]}
    40. };
    41. int[][] d1 = {
    42. {arr[0][3], arr[0][1], arr[0][2]},
    43. {arr[1][3], arr[1][1], arr[1][2]},
    44. {arr[2][3], arr[2][1], arr[2][2]}
    45. };
    46. int[][] d2 = {
    47. {arr[0][0], arr[0][3], arr[0][2]},
    48. {arr[1][0], arr[1][3], arr[1][2]},
    49. {arr[2][0], arr[2][3], arr[2][2]}
    50. };
    51. int[][] d3 = {
    52. {arr[0][0], arr[0][1], arr[0][3]},
    53. {arr[1][0], arr[1][1], arr[1][3]},
    54. {arr[2][0], arr[2][1], arr[2][3]}
    55. };
    56. */
    57. System.out.println("----------------");
    58. List<BigDecimal[][]> determinant = new ArrayList<>(arr.length + 1);
    59. for (int i = 0; i < arr.length + 1; i++) {
    60. System.out.println("第" + i + "个行列式:");
    61. BigDecimal[][] d = new BigDecimal[arr.length][arr.length];
    62. for (int row = 0; row < d.length; row++) {
    63. for (int col = 0; col < d.length; col++) {
    64. if (i == 0) {
    65. d[row][col] = arr[row][col];
    66. } else {
    67. if (col == i - 1) {
    68. d[row][col] = arr[row][arr.length];
    69. } else {
    70. d[row][col] = arr[row][col];
    71. }
    72. }
    73. }
    74. }
    75. determinant.add(d);
    76. System.out.println(Arrays.deepToString(d));
    77. }
    78. /*
    79. int D = determinant(d);
    80. int D1 = determinant(d1);
    81. int D2 = determinant(d2);
    82. int D3 = determinant(d3);
    83. System.out.println("D=" + D + ",D1=" + D1 + ",D2=" + D2 + ",D3=" + D3);
    84. */
    85. System.out.println("----------------");
    86. System.out.println("行列式的解:");
    87. List<BigDecimal> D = new ArrayList<>();
    88. for (int i = 0; i < determinant.size(); i++) {
    89. BigDecimal det = det(determinant.get(i));
    90. if (det.compareTo(BigDecimal.ZERO) == 0 && i == 0) {
    91. throw new Exception("方程无解");
    92. }
    93. D.add(det);
    94. }
    95. System.out.println(D);
    96. /*
    97. int x = D1 / D;
    98. int y = D2 / D;
    99. int z = D3 / D;
    100. System.out.println("x=" + x + ",y=" + y + ",z=" + z);
    101. */
    102. System.out.println("----------------");
    103. System.out.println("方程的解:");
    104. List<BigDecimal> result = new ArrayList<>();
    105. for (int i = 1; i < D.size(); i++) {
    106. result.add(D.get(i).divide(D.get(0), 4, RoundingMode.HALF_UP));
    107. }
    108. System.out.println(result);
    109. }
    110. /**
    111. * 行列式的解
    112. */
    113. private BigDecimal detResult;
    114. /**
    115. * 求一个行列式的解,例如
    116. * (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])
    117. * - (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]);
    118. *
    119. * @param d 行列式数组
    120. * @return 行列式的解
    121. */
    122. private BigDecimal det(BigDecimal[][] d) {
    123. // 初始化结果
    124. detResult = BigDecimal.ZERO;
    125. // 初始化路径
    126. int[] path = new int[d.length];
    127. Arrays.fill(path, -1);
    128. // 从0行0列开始遍历
    129. // System.out.println("行列式的路径:");
    130. return detRecursion(d, 0, path, BigDecimal.ONE);
    131. }
    132. /**
    133. * 递归求行列式的解
    134. *
    135. * @param d 行列式数组
    136. * @param row 当前行数
    137. * @param path 递归路径,保存的key是行数,value是列数,保证每行不在同一列上
    138. * @param multiplyResult 保存的是当前所递归路径的乘积
    139. * @return 行列式的解
    140. */
    141. private BigDecimal detRecursion(BigDecimal[][] d, int row, int[] path, BigDecimal multiplyResult) {
    142. int length = d.length;
    143. // 当行数大于总行数,说明递归到最底层了
    144. if (row >= length) {
    145. multiplyResult = multiplyResult.multiply(new BigDecimal(inversionNumber(path) % 2 == 0 ? 1 : -1));
    146. // System.out.println("路径:"+ Arrays.toString(path)+ ",结果:"+multiplyResult);
    147. detResult = detResult.add(multiplyResult);
    148. return detResult;
    149. }
    150. // 对每一列进行遍历,确保每一种组合都能遍历到
    151. for (int col = 0; col < length; col++) {
    152. // 对路径进行遍历,如果当前列与之前的列在同一列,则换下一列
    153. boolean flag = false;
    154. for (int i : path) {
    155. if (i == col) {
    156. flag = true;
    157. break;
    158. }
    159. }
    160. if (!flag) {
    161. // 如果当前列可用,将列放到路径中
    162. path[row] = col;
    163. // 进行下一行递归
    164. detRecursion(d, row + 1, path, d[row][col].multiply(multiplyResult));
    165. // 还原路径
    166. path[row] = -1;
    167. }
    168. }
    169. return detResult;
    170. }
    171. /**
    172. * 计算逆序数 e.g. 1,2,4,3 逆序数个数是 1 1,2,3,4 逆序数个数是 0
    173. *
    174. * @param arr 数组
    175. * @return 逆序数个数
    176. */
    177. private int inversionNumber(int[] arr) {
    178. int count = 0;
    179. for (int i = 0; i < arr.length; i++) {
    180. for (int j = i + 1; j < arr.length; j++) {
    181. if (arr[i] > arr[j]) {
    182. count++;
    183. }
    184. }
    185. }
    186. return count;
    187. }
    188. /**
    189. * 读取文件中的
    190. */
    191. private BigDecimal[][] readFile(String filepath) throws IOException {
    192. File file = new File(filepath);
    193. BigDecimal[][] arr;
    194. try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
    195. List<String> lines = reader.lines().collect(Collectors.toList());
    196. arr = new BigDecimal[lines.size()][];
    197. for (int i = 0; i < lines.size(); i++) {
    198. String line = lines.get(i).trim();
    199. if (!StringUtils.isEmpty(line)) {
    200. String[] arrStr = line.split("[,,]");
    201. arr[i] = new BigDecimal[arrStr.length];
    202. for (int j = 0; j < arrStr.length; j++) {
    203. arr[i][j] = new BigDecimal(arrStr[j].trim());
    204. }
    205. }
    206. }
    207. }
    208. System.out.println(Arrays.deepToString(arr));
    209. return arr;
    210. }
    211. }

    文本内容:

    1. 2, 3, 1, 6
    2. 1, -1, 2, -1
    3. 1, 2, -1, 5

    输出:

    1. [[2, 3, 1, 6], [1, -1, 2, -1], [1, 2, -1, 5]]
    2. ----------------
    3. 0个行列式:
    4. [[2, 3, 1], [1, -1, 2], [1, 2, -1]]
    5. 1个行列式:
    6. [[6, 3, 1], [-1, -1, 2], [5, 2, -1]]
    7. 2个行列式:
    8. [[2, 6, 1], [1, -1, 2], [1, 5, -1]]
    9. 3个行列式:
    10. [[2, 3, 6], [1, -1, -1], [1, 2, 5]]
    11. ----------------
    12. 行列式的解:
    13. [6, 12, 6, -6]
    14. ----------------
    15. 方程的解:
    16. [2, 1, -1]