高斯消去法解方程组
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含 n+1n+1 个实数,表示一个方程的 nn 个系数以及等号右侧的常数。
输出格式
如果给定线性方程组存在唯一解,则输出共 nn 行,其中第 ii 行输出第 ii 个未知数的解,结果保留两位小数。
如果给定线性方程组存在无数解,则输出 Infinite group solutions
。
如果给定线性方程组无解,则输出 No solution
。
高斯消去法的步骤:
- 找到当前列绝对值最大的一行
- 把它换到最上面一行
- 将该行的第一个数变为1
- 把下面所有行的该列消为0
解的形式:
- 完美阶梯型:唯一解
- 零=非零:无解
- 零=零:无穷解
代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); double arr[][] = new double[n][n+1]; for (int i = 0;i<n;i++){ for (int j = 0;j<=n;j++){ arr[i][j] = scanner.nextDouble(); } } int index = guass(arr); if (index==0){ for (int i = 0;i<n;i++){ if(arr[i][n]==-0.0) arr[i][n]=0.0; System.out.println(String.format("%.2f",arr[i][n])); } }else if (index==1){ System.out.println("Infinite group solutions"); }else { System.out.println("No solution"); }
} public static int guass(double arr[][]){
int n = arr.length; int r = 0,c = 0; for (r = 0,c = 0;c<n;c++){ int t = r; for (int i = r;i<n;i++){ if (Math.abs(arr[t][c])<Math.abs(arr[i][c])){ t = i; } } if(Math.abs(arr[t][c])<0.000001) continue; for (int i = c;i<=n;i++){ double temp = arr[t][i]; arr[t][i] = arr[r][i]; arr[r][i] = temp; } for (int i = n;i>=c;i--){ arr[r][i]/= arr[r][c]; } for (int i = r+1;i<n;i++){ if(Math.abs(arr[i][c])>0.000001) { for (int j = n; j >= c; j--) { arr[i][j]-= arr[r][j] * arr[i][c]; } } } r++; } if (r<n){ for (int i = r;i<n;i++){ if (Math.abs(arr[i][n])>0.000001) return 2; } return 1; }
for (int i = n-1;i>=0;i--){ for (int j = i+1;j<n;j++){ arr[i][n]-=arr[i][j]*arr[j][n]; } } return 0; } }
|
高斯消元代码中最难理解的就是往回推的最后一步
1 2 3
| for (int i = n - 1; i >= 0; i -- ) for (int j = i + 1; j < n; j ++ ) a[i][n] -= a[j][n] * a[i][j];
|
这里的 i,j 其实代表的是 xi和xj ,对于 i 行中的 xj 对应的系数是 a[i][j]
,而a[i][j]
则代表了此时 i 行的多项式的结果,为了得到xi的解(xi的系数是1)就需要此时的结果减去后面的多项式的和即
1 2
| for(int j = i + 1; j < n; j ++ ) a -= a * a;//x_j * x_j的系数
|