Advertisement
MrGhost75

LAB3_SYSTEM

Jun 4th, 2020
737
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.00 KB | None | 0 0
  1.  
  2. import java.io.*;
  3.  
  4. /*
  5. (1) Решить СЛАУ методами Гаусса и Крамера(для последнего нужна рекурсивная процедура)
  6. (2) Матрица не обязательно квадратная!
  7. (3) Не просто сравнить решения двумя методами, а ещё и дать количественную характеристику
  8. отклонения двух решений(при помощи среднего квадратичного отклонения)
  9. и вывести отличие на экран.
  10. */
  11.  
  12.  
  13. public class Main {
  14.  
  15.     public static void main(String[] args) throws IOException {
  16.         BufferedReader fileReader = new BufferedReader(new FileReader("MATRIX.txt"));
  17.         BufferedWriter fileWriter = new BufferedWriter(new FileWriter("RESULT.txt"));
  18.         //Если flag == 0, то матрица квадратная.
  19.         //Если flag == 1, то матрица прямоугольная, решений бесконечно.
  20.         //Если flag == 2, то матрица прямоугольная, решений нет.
  21.         int flag = 0;
  22.  
  23.         //Определим количество столбцов и количество строк в нашей системе:
  24.         int n = 0;
  25.         int m;
  26.  
  27.         String line = fileReader.readLine();
  28.  
  29.         String[] firstLine = line.split("\\s+"); //Разобъем первую строку на массив
  30.         m = firstLine.length; //Найдем кол-во столбцов
  31.  
  32.         while(line != null) {
  33.             n++;       //Находим кол-во строк
  34.             line = fileReader.readLine();
  35.         }
  36.         fileReader.close();
  37.  
  38.         //Создадим массив n * m:
  39.         double[][] matrix = new double[n][m];
  40.  
  41.         //Теперь считаем файл заново, записывая данные в массив размерности n * m:
  42.         fileReader = new BufferedReader(new FileReader("MATRIX.txt"));
  43.         for (int i = 0; i < n; i++) {
  44.             String[] sNumbers = fileReader.readLine().split("\\s+");
  45.             for (int j = 0; j < m; j++) {
  46.                 matrix[i][j] = Double.parseDouble(sNumbers[j]);
  47.             }
  48.         }
  49.  
  50.         //Выведем изначальную систему на экран
  51.         fileWriter.write("heyВаша матрица:\n");
  52.         System.out.println("Ваша матрица:");
  53.         printMatrix(matrix, fileWriter);
  54.  
  55.         //"Пройдёмся" прямым ходом по Гауссу в нашей системе и выведем полученную матрицу на экран:
  56.         gaussForward(matrix);
  57.  
  58.         fileWriter.write("\nВаша матрица после приведения к ступенчатому виду:\n");
  59.         System.out.println("\nВаша матрица после приведения к ступенчатому виду:");
  60.         printMatrix(matrix, fileWriter);
  61.  
  62.         //Уберём нулевые строки и выведем преобразованную матрицу на экран:
  63.         matrix = linearDependentStringRemoval(matrix);
  64.  
  65.         fileWriter.write("\nВаша матрица, после того, как из неё были удалены все нулевые строки(если таковые имелись):\n");
  66.         System.out.println("\nВаша матрица, после того, как из неё были удалены все нулевые строки(если таковые имелись):");
  67.         printMatrix(matrix, fileWriter);
  68.  
  69.         //Определим наш "флаг".
  70.         //(определим, есть ли решения для нашей системы, и если да, то сколько их(1 или бесконечно)).
  71.         flag = setFlag(matrix, flag);
  72.  
  73.         //Применим метод решения в зависимости от флага:
  74.         switch(flag) {
  75.  
  76.             case (0): //Матрица квадратная, метод Крамера и метод Гаусса.
  77.                 fileWriter.write("\nМатрица квадратная (n == m), следовательно есть 1 решение.\n");
  78.                 fileWriter.write("Найдём его при помощи метода Гаусса и метода Крамера.\n");
  79.                 System.out.println("\nМатрица квадратная (n == m), следовательно есть 1 решение.");
  80.                 System.out.println("Найдём его при помощи метода Гаусса и метода Крамера.");
  81.  
  82.                 //Результат по методу Крамера.
  83.                 double[] resultKramer = kramerMethod(matrix);
  84.                 fileWriter.write("\nРезультат по методу Крамера:\n");
  85.                 System.out.println("\nРезультат по методу Крамера:");
  86.                 for (int i = 0; i < matrix.length; i++) {
  87.                     fileWriter.write("x" + (i+1) + " = " + resultKramer[i] + "\n");
  88.                     System.out.println("x" + (i+1) + " = " + resultKramer[i]);
  89.                 }
  90.  
  91.                 //Результат по методу Гаусса.
  92.                 double[] resultGauss = gaussMethod(matrix, flag);
  93.                 fileWriter.write("\nРезультат по методу Гаусса:\n");
  94.                 System.out.println("\nРезультат по методу Гаусса:");
  95.                 for (int i = 0; i < matrix.length; i++) {
  96.                     fileWriter.write("x" + (i+1) + " = " + resultGauss[i] + "\n");
  97.                     System.out.println("x" + (i+1) + " = " + resultGauss[i]);
  98.                 }
  99.  
  100.                 //Среднеквадратическое отклонение двух решений.
  101.                 standardDeviation(resultKramer, resultGauss, fileWriter);
  102.  
  103.                 break;
  104.  
  105.             case (1): //Матрица прямоугольная, решений бесконечно, метод Гаусса.
  106.                 fileWriter.write("\nМатрица прямоугольная (n < m), решений бесконечно.\n");
  107.                 fileWriter.write("Для дальнейшего решения присвоим свободным переменным конкретное значение - ноль.\n");
  108.                 System.out.println("\nМатрица прямоугольная (n < m), решений бесконечно.");
  109.                 System.out.println("Для дальнейшего решения присвоим свободным переменным конкретное значение - ноль.");
  110.  
  111.                 //Метод Гаусса для бесконечного количества решений.
  112.                 double[] infResultGauss = gaussMethod(matrix, flag);
  113.                 fileWriter.write("\nРезультат по методу Гаусса:\n");
  114.                 System.out.println("\nРезультат по методу Гаусса:");
  115.                 for (int i = 0; i < matrix[0].length - 1; i++) {
  116.                     fileWriter.write("x" + (i+1) + " = " + infResultGauss[i] + "\n");
  117.                     System.out.println("x" + (i+1) + " = " + infResultGauss[i]);
  118.                 }
  119.  
  120.                 break;
  121.  
  122.             case (2): //Система не имеет решений(есть строка вида 0 + 0 + 0 + ... + 0 = k, где k - константа, не равная нулю).
  123.                 fileWriter.write("\n\nСистема не имеет решений (есть строка вида 0 + 0 + 0 + ... + 0 = k, где k - константа, не равная нулю).\n");
  124.                 System.out.println("\nСистема не имеет решений (есть строка вида 0 + 0 + 0 + ... + 0 = k, где k - константа, не равная нулю).");
  125.                 break;
  126.         }
  127.  
  128.     }
  129.  
  130.     //Функция вывода матрицы на экран.
  131.     public static void printMatrix(double[][] matrix, BufferedWriter writer) throws IOException {
  132.         for (int i = 0; i < matrix.length; i++) {
  133.             for (int j = 0; j < matrix[i].length; j++) {
  134.                 writer.write(matrix[i][j] + " ");
  135.                 System.out.print(matrix[i][j] + " ");
  136.             }
  137.             writer.write("\n");
  138.             System.out.println();
  139.         }
  140.     }
  141.  
  142.     //Функция удаления строки из матрицы по заданному номеру.
  143.     public static double[][] delStr(double[][] matrix, int str) {
  144.         int n = matrix.length;
  145.         int m = matrix[0].length;
  146.         double[][] newMatrix = new double[n - 1][m]; //newMatrix будет на одну строку меньше, чем matrix.
  147.  
  148.         for (int i = str - 1; i < n - 1; i++) {
  149.             matrix[i] = matrix[i + 1]; //каждой строке, начиная с заданной, присвоим строку, что стоит после неё.
  150.         }
  151.         for (int i = 0; i < n - 1; i++) {
  152.             for (int j = 0; j < m; j++) {
  153.                 newMatrix[i][j] = matrix[i][j]; //запишем в newMatrix элементы из matrix, не учитывая последнюю строку
  154.             }
  155.         }
  156.         return newMatrix;
  157.     }
  158.  
  159.     //Функция поиска и удаления всех линейно-зависимых строк(0 + 0 + 0 + ... + 0 = 0).
  160.     public static double[][] linearDependentStringRemoval(double[][] matrix) {
  161.  
  162.         //Ищем количество линейно-зависимых строк.
  163.         int amountOfLinearDependentStrings = 0;
  164.         boolean zero = false;
  165.         for (int i = 0; i < matrix.length; i++) {
  166.             for (int j = 0; j < matrix[0].length; j++) {
  167.                 if(matrix[i][j] == 0) zero = true;
  168.                 else {
  169.                     zero = false;
  170.                     break;
  171.                 }
  172.             }
  173.             if (zero) amountOfLinearDependentStrings++;
  174.             zero = false;
  175.         }
  176.  
  177.  
  178.         //Пока нулевые строки есть...
  179.         while(amountOfLinearDependentStrings != 0) {
  180.             //Удаляем их, используя поиск из прошлого блока кода. Удаление выполняется при помощи ф-ии delStr.
  181.             for (int i = 0; i < matrix.length; i++) {
  182.                 for (int j = 0; j < matrix[0].length; j++) {
  183.                     if (matrix[i][j] == 0) zero = true;
  184.                     else {
  185.                         zero = false;
  186.                         break;
  187.                     }
  188.                 }
  189.                 if (zero) {
  190.                     matrix = delStr(matrix, i + 1); //Удалим (i+1)-ю строку (т.к. мы запрашиваем номер строки, а не индекс).
  191.                     zero = false;
  192.                     break;
  193.                 }
  194.             }
  195.             amountOfLinearDependentStrings--;
  196.         }
  197.  
  198.         return matrix;
  199.     }
  200.  
  201.     //Функция для определения нашего "флага".
  202.     public static int setFlag(double[][] matrix, int flag) {
  203.         int n = matrix.length;
  204.         int m = matrix[0].length - 1; //Матрица системы(не расширенная)
  205.  
  206.         //Если все коэффициенты ai при иксах = 0, а свободный член = k (он же элемент matrix[i][m]), где k - константа, не равная нулю, то решений нет.
  207.         boolean ai = false;
  208.         for (int i = 0; i < n; i++) {
  209.             for (int j = 0; j < m; j++) {
  210.                 if (matrix[i][j] == 0) ai = true;
  211.                 else {
  212.                     ai = false;
  213.                     break;
  214.                 }
  215.             }
  216.             if (ai && (matrix[i][m] != 0)) {
  217.                 flag = 2;
  218.                 return flag;
  219.             }
  220.         }
  221.  
  222.         //В случае невыполнения предыдущего условия, если матрица квадратная, то всего одно решение.
  223.         if (n == m) flag = 0;
  224.  
  225.         //Иначе их бесконечно много.
  226.         else if (n < m) flag = 1;
  227.  
  228.         return flag;
  229.     }
  230.  
  231.     //Функция сдвига заданной строки в конец.
  232.     public static void changeRows(double[][] matrix, int position) {
  233.         int n = matrix.length;
  234.         double[] temp = matrix[position];
  235.         for (int i = position; i < n - 1; i++) {
  236.             matrix[i] = matrix[i + 1]; //каждой строке, начиная с заданной, присвоим строку, что стоит после неё.
  237.         }
  238.         matrix[n-1] = temp;
  239.     }
  240.  
  241.     //Функция прямого хода по Гауссу.
  242.     public static void gaussForward(double[][] matrix) {
  243.         int n = matrix.length;
  244.         int m = matrix[0].length;
  245.  
  246.         double delta;
  247.         for (int k = 0; k < n; k++) {
  248.             for (int i = k + 1; i < n; i++) {
  249.                 while(matrix[k][k] == 0) {
  250.                     changeRows(matrix, k);
  251.                 }
  252.                 delta = matrix[i][k] / matrix[k][k]; // формула (1)
  253.                 for (int j = k; j < m; j++) {
  254.                     matrix[i][j] -= delta * matrix[k][j]; // формула (2)
  255.                 }
  256.             }
  257.         }
  258.     }
  259.  
  260.     //Определитель рекурсивно.
  261.     public static double det(double[][] A) {
  262.         int n = A.length;
  263.         if(n == 1) return A[0][0];
  264.         double ans = 0;
  265.         double[][] B = new double[n-1][n-1];
  266.         int l = 1;
  267.         for(int i = 0; i < n; ++i) {
  268.             int x = 0, y = 0;
  269.             for(int j = 1; j < n; ++j) {
  270.                 for(int k = 0; k < n; ++k) {
  271.                     if(i == k) continue;
  272.                     B[x][y] = A[j][k];
  273.                     ++y;
  274.                     if(y == n - 1){
  275.                         y = 0;
  276.                         ++x;
  277.                     }
  278.                 }
  279.             }
  280.             ans += l * A[0][i] * det(B);
  281.             l *= (-1);
  282.         }
  283.         return ans;
  284.     }
  285.  
  286.     //Метод Крамера.
  287.     public static double[] kramerMethod(double[][] matrix) {
  288.         int n = matrix.length;
  289.         int m = matrix[0].length;
  290.  
  291.         double delta = det(matrix);
  292.         double[][] temp = new double[n][n];
  293.         double[] result = new double[n];
  294.  
  295.  
  296.         double[] b = new double[n];//Столбец свободных членов
  297.         for (int i = 0; i < n; i++) {
  298.             b[i] = matrix[i][m-1];
  299.         }
  300.  
  301.         for (int k = 0; k < n; k++) {
  302.             for (int i = 0; i < n; i++) {
  303.                 for (int j = 0; j < n; j++) {
  304.                     temp[i][j] = matrix[i][j];
  305.                 }
  306.             }
  307.             for (int i = 0; i < n; i++) {
  308.                 temp[i][k] = b[i];
  309.             }
  310.             result[k] = det(temp) / delta;
  311.         }
  312.         return result;
  313.  
  314.     }
  315.  
  316.     //Метод Гаусса обратный.
  317.     public static double[] gaussMethod(double[][] matrix, int flag) {
  318.         int n = matrix.length;
  319.         int m = matrix[0].length;
  320.         double[] result = new double[m-1];
  321.  
  322.         double[] b = new double[n];//Столбец свободных членов
  323.         for (int i = 0; i < n; i++) {
  324.             b[i] = matrix[i][m - 1];
  325.         }
  326.  
  327.         if (flag == 0) {
  328.             for (int i = n - 1; i >= 0; i--) {
  329.                 double sum = 0.0;
  330.                 for (int j = i + 1; j < n; j++) {
  331.                     sum += matrix[i][j] * result[j];
  332.                 }
  333.                 result[i] = (b[i] - sum) / matrix[i][i];
  334.             }
  335.             return result;
  336.         }
  337.  
  338.         else if (flag == 1) {
  339.             for (int i = 0; i < n; i++) {
  340.                 for (int j = n; j < m - 1; j++) {
  341.                     matrix[i][j] = 0;
  342.                 }
  343.             }
  344.  
  345.             for (int i = n - 1; i >= 0; i--) {
  346.                 double sum = 0.0;
  347.                 for (int j = i + 1; j < n; j++) {
  348.                     sum += matrix[i][j] * result[j];
  349.                 }
  350.                 result[i] = (b[i] - sum) / matrix[i][i];
  351.             }
  352.  
  353.             return result;
  354.         }
  355.  
  356.         return result;
  357.     }
  358.  
  359.     //Среднеквадратическое отклонение двух решений:
  360.     public static void standardDeviation(double[] kramer, double[] gauss, BufferedWriter writer) throws IOException {
  361.         double deviation = 0;
  362.         for (int i = 0; i < kramer.length; i++) {
  363.             deviation += (kramer[i] - gauss[i])*(kramer[i] - gauss[i]);
  364.         }
  365.         writer.write("\n\nСреднеквадратическое отклонение равно: " + Math.sqrt(deviation));
  366.         System.out.println("\nСреднеквадратическое отклонение равно: " + Math.sqrt(deviation));
  367.     }
  368.  
  369. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement