Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.*;
- /*
- (1) Решить СЛАУ методами Гаусса и Крамера(для последнего нужна рекурсивная процедура)
- (2) Матрица не обязательно квадратная!
- (3) Не просто сравнить решения двумя методами, а ещё и дать количественную характеристику
- отклонения двух решений(при помощи среднего квадратичного отклонения)
- и вывести отличие на экран.
- */
- public class Main {
- public static void main(String[] args) throws IOException {
- BufferedReader fileReader = new BufferedReader(new FileReader("MATRIX.txt"));
- BufferedWriter fileWriter = new BufferedWriter(new FileWriter("RESULT.txt"));
- //Если flag == 0, то матрица квадратная.
- //Если flag == 1, то матрица прямоугольная, решений бесконечно.
- //Если flag == 2, то матрица прямоугольная, решений нет.
- int flag = 0;
- //Определим количество столбцов и количество строк в нашей системе:
- int n = 0;
- int m;
- String line = fileReader.readLine();
- String[] firstLine = line.split("\\s+"); //Разобъем первую строку на массив
- m = firstLine.length; //Найдем кол-во столбцов
- while(line != null) {
- n++; //Находим кол-во строк
- line = fileReader.readLine();
- }
- fileReader.close();
- //Создадим массив n * m:
- double[][] matrix = new double[n][m];
- //Теперь считаем файл заново, записывая данные в массив размерности n * m:
- fileReader = new BufferedReader(new FileReader("MATRIX.txt"));
- for (int i = 0; i < n; i++) {
- String[] sNumbers = fileReader.readLine().split("\\s+");
- for (int j = 0; j < m; j++) {
- matrix[i][j] = Double.parseDouble(sNumbers[j]);
- }
- }
- //Выведем изначальную систему на экран
- fileWriter.write("heyВаша матрица:\n");
- System.out.println("Ваша матрица:");
- printMatrix(matrix, fileWriter);
- //"Пройдёмся" прямым ходом по Гауссу в нашей системе и выведем полученную матрицу на экран:
- gaussForward(matrix);
- fileWriter.write("\nВаша матрица после приведения к ступенчатому виду:\n");
- System.out.println("\nВаша матрица после приведения к ступенчатому виду:");
- printMatrix(matrix, fileWriter);
- //Уберём нулевые строки и выведем преобразованную матрицу на экран:
- matrix = linearDependentStringRemoval(matrix);
- fileWriter.write("\nВаша матрица, после того, как из неё были удалены все нулевые строки(если таковые имелись):\n");
- System.out.println("\nВаша матрица, после того, как из неё были удалены все нулевые строки(если таковые имелись):");
- printMatrix(matrix, fileWriter);
- //Определим наш "флаг".
- //(определим, есть ли решения для нашей системы, и если да, то сколько их(1 или бесконечно)).
- flag = setFlag(matrix, flag);
- //Применим метод решения в зависимости от флага:
- switch(flag) {
- case (0): //Матрица квадратная, метод Крамера и метод Гаусса.
- fileWriter.write("\nМатрица квадратная (n == m), следовательно есть 1 решение.\n");
- fileWriter.write("Найдём его при помощи метода Гаусса и метода Крамера.\n");
- System.out.println("\nМатрица квадратная (n == m), следовательно есть 1 решение.");
- System.out.println("Найдём его при помощи метода Гаусса и метода Крамера.");
- //Результат по методу Крамера.
- double[] resultKramer = kramerMethod(matrix);
- fileWriter.write("\nРезультат по методу Крамера:\n");
- System.out.println("\nРезультат по методу Крамера:");
- for (int i = 0; i < matrix.length; i++) {
- fileWriter.write("x" + (i+1) + " = " + resultKramer[i] + "\n");
- System.out.println("x" + (i+1) + " = " + resultKramer[i]);
- }
- //Результат по методу Гаусса.
- double[] resultGauss = gaussMethod(matrix, flag);
- fileWriter.write("\nРезультат по методу Гаусса:\n");
- System.out.println("\nРезультат по методу Гаусса:");
- for (int i = 0; i < matrix.length; i++) {
- fileWriter.write("x" + (i+1) + " = " + resultGauss[i] + "\n");
- System.out.println("x" + (i+1) + " = " + resultGauss[i]);
- }
- //Среднеквадратическое отклонение двух решений.
- standardDeviation(resultKramer, resultGauss, fileWriter);
- break;
- case (1): //Матрица прямоугольная, решений бесконечно, метод Гаусса.
- fileWriter.write("\nМатрица прямоугольная (n < m), решений бесконечно.\n");
- fileWriter.write("Для дальнейшего решения присвоим свободным переменным конкретное значение - ноль.\n");
- System.out.println("\nМатрица прямоугольная (n < m), решений бесконечно.");
- System.out.println("Для дальнейшего решения присвоим свободным переменным конкретное значение - ноль.");
- //Метод Гаусса для бесконечного количества решений.
- double[] infResultGauss = gaussMethod(matrix, flag);
- fileWriter.write("\nРезультат по методу Гаусса:\n");
- System.out.println("\nРезультат по методу Гаусса:");
- for (int i = 0; i < matrix[0].length - 1; i++) {
- fileWriter.write("x" + (i+1) + " = " + infResultGauss[i] + "\n");
- System.out.println("x" + (i+1) + " = " + infResultGauss[i]);
- }
- break;
- case (2): //Система не имеет решений(есть строка вида 0 + 0 + 0 + ... + 0 = k, где k - константа, не равная нулю).
- fileWriter.write("\n\nСистема не имеет решений (есть строка вида 0 + 0 + 0 + ... + 0 = k, где k - константа, не равная нулю).\n");
- System.out.println("\nСистема не имеет решений (есть строка вида 0 + 0 + 0 + ... + 0 = k, где k - константа, не равная нулю).");
- break;
- }
- }
- //Функция вывода матрицы на экран.
- public static void printMatrix(double[][] matrix, BufferedWriter writer) throws IOException {
- for (int i = 0; i < matrix.length; i++) {
- for (int j = 0; j < matrix[i].length; j++) {
- writer.write(matrix[i][j] + " ");
- System.out.print(matrix[i][j] + " ");
- }
- writer.write("\n");
- System.out.println();
- }
- }
- //Функция удаления строки из матрицы по заданному номеру.
- public static double[][] delStr(double[][] matrix, int str) {
- int n = matrix.length;
- int m = matrix[0].length;
- double[][] newMatrix = new double[n - 1][m]; //newMatrix будет на одну строку меньше, чем matrix.
- for (int i = str - 1; i < n - 1; i++) {
- matrix[i] = matrix[i + 1]; //каждой строке, начиная с заданной, присвоим строку, что стоит после неё.
- }
- for (int i = 0; i < n - 1; i++) {
- for (int j = 0; j < m; j++) {
- newMatrix[i][j] = matrix[i][j]; //запишем в newMatrix элементы из matrix, не учитывая последнюю строку
- }
- }
- return newMatrix;
- }
- //Функция поиска и удаления всех линейно-зависимых строк(0 + 0 + 0 + ... + 0 = 0).
- public static double[][] linearDependentStringRemoval(double[][] matrix) {
- //Ищем количество линейно-зависимых строк.
- int amountOfLinearDependentStrings = 0;
- boolean zero = false;
- for (int i = 0; i < matrix.length; i++) {
- for (int j = 0; j < matrix[0].length; j++) {
- if(matrix[i][j] == 0) zero = true;
- else {
- zero = false;
- break;
- }
- }
- if (zero) amountOfLinearDependentStrings++;
- zero = false;
- }
- //Пока нулевые строки есть...
- while(amountOfLinearDependentStrings != 0) {
- //Удаляем их, используя поиск из прошлого блока кода. Удаление выполняется при помощи ф-ии delStr.
- for (int i = 0; i < matrix.length; i++) {
- for (int j = 0; j < matrix[0].length; j++) {
- if (matrix[i][j] == 0) zero = true;
- else {
- zero = false;
- break;
- }
- }
- if (zero) {
- matrix = delStr(matrix, i + 1); //Удалим (i+1)-ю строку (т.к. мы запрашиваем номер строки, а не индекс).
- zero = false;
- break;
- }
- }
- amountOfLinearDependentStrings--;
- }
- return matrix;
- }
- //Функция для определения нашего "флага".
- public static int setFlag(double[][] matrix, int flag) {
- int n = matrix.length;
- int m = matrix[0].length - 1; //Матрица системы(не расширенная)
- //Если все коэффициенты ai при иксах = 0, а свободный член = k (он же элемент matrix[i][m]), где k - константа, не равная нулю, то решений нет.
- boolean ai = false;
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- if (matrix[i][j] == 0) ai = true;
- else {
- ai = false;
- break;
- }
- }
- if (ai && (matrix[i][m] != 0)) {
- flag = 2;
- return flag;
- }
- }
- //В случае невыполнения предыдущего условия, если матрица квадратная, то всего одно решение.
- if (n == m) flag = 0;
- //Иначе их бесконечно много.
- else if (n < m) flag = 1;
- return flag;
- }
- //Функция сдвига заданной строки в конец.
- public static void changeRows(double[][] matrix, int position) {
- int n = matrix.length;
- double[] temp = matrix[position];
- for (int i = position; i < n - 1; i++) {
- matrix[i] = matrix[i + 1]; //каждой строке, начиная с заданной, присвоим строку, что стоит после неё.
- }
- matrix[n-1] = temp;
- }
- //Функция прямого хода по Гауссу.
- public static void gaussForward(double[][] matrix) {
- int n = matrix.length;
- int m = matrix[0].length;
- double delta;
- for (int k = 0; k < n; k++) {
- for (int i = k + 1; i < n; i++) {
- while(matrix[k][k] == 0) {
- changeRows(matrix, k);
- }
- delta = matrix[i][k] / matrix[k][k]; // формула (1)
- for (int j = k; j < m; j++) {
- matrix[i][j] -= delta * matrix[k][j]; // формула (2)
- }
- }
- }
- }
- //Определитель рекурсивно.
- public static double det(double[][] A) {
- int n = A.length;
- if(n == 1) return A[0][0];
- double ans = 0;
- double[][] B = new double[n-1][n-1];
- int l = 1;
- for(int i = 0; i < n; ++i) {
- int x = 0, y = 0;
- for(int j = 1; j < n; ++j) {
- for(int k = 0; k < n; ++k) {
- if(i == k) continue;
- B[x][y] = A[j][k];
- ++y;
- if(y == n - 1){
- y = 0;
- ++x;
- }
- }
- }
- ans += l * A[0][i] * det(B);
- l *= (-1);
- }
- return ans;
- }
- //Метод Крамера.
- public static double[] kramerMethod(double[][] matrix) {
- int n = matrix.length;
- int m = matrix[0].length;
- double delta = det(matrix);
- double[][] temp = new double[n][n];
- double[] result = new double[n];
- double[] b = new double[n];//Столбец свободных членов
- for (int i = 0; i < n; i++) {
- b[i] = matrix[i][m-1];
- }
- for (int k = 0; k < n; k++) {
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) {
- temp[i][j] = matrix[i][j];
- }
- }
- for (int i = 0; i < n; i++) {
- temp[i][k] = b[i];
- }
- result[k] = det(temp) / delta;
- }
- return result;
- }
- //Метод Гаусса обратный.
- public static double[] gaussMethod(double[][] matrix, int flag) {
- int n = matrix.length;
- int m = matrix[0].length;
- double[] result = new double[m-1];
- double[] b = new double[n];//Столбец свободных членов
- for (int i = 0; i < n; i++) {
- b[i] = matrix[i][m - 1];
- }
- if (flag == 0) {
- for (int i = n - 1; i >= 0; i--) {
- double sum = 0.0;
- for (int j = i + 1; j < n; j++) {
- sum += matrix[i][j] * result[j];
- }
- result[i] = (b[i] - sum) / matrix[i][i];
- }
- return result;
- }
- else if (flag == 1) {
- for (int i = 0; i < n; i++) {
- for (int j = n; j < m - 1; j++) {
- matrix[i][j] = 0;
- }
- }
- for (int i = n - 1; i >= 0; i--) {
- double sum = 0.0;
- for (int j = i + 1; j < n; j++) {
- sum += matrix[i][j] * result[j];
- }
- result[i] = (b[i] - sum) / matrix[i][i];
- }
- return result;
- }
- return result;
- }
- //Среднеквадратическое отклонение двух решений:
- public static void standardDeviation(double[] kramer, double[] gauss, BufferedWriter writer) throws IOException {
- double deviation = 0;
- for (int i = 0; i < kramer.length; i++) {
- deviation += (kramer[i] - gauss[i])*(kramer[i] - gauss[i]);
- }
- writer.write("\n\nСреднеквадратическое отклонение равно: " + Math.sqrt(deviation));
- System.out.println("\nСреднеквадратическое отклонение равно: " + Math.sqrt(deviation));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement