Метод Крамера решения СЛАУ на С++

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 7 мес., 2 нед. назад.

  • Автор
    Сообщения
  • #3546

    В соседней теме был подробно разобран алгоритм метода Крамера, используемый для решения системы линейных алгебраических уравнений. Теперь разберем реализацию метода на С++. Для начала напишем модульные тесты, описывающие случай системы, имеющей решение и системы без решения:

    BOOST_AUTO_TEST_CASE(CramerSolving_Solution) {
      const int size = 3;
      std::vector<std::vector<double> >
        matrix = {{5,7,6}, {3, 16,19}, {13,10,7}};
      std::vector<double>
        free_term_column = {73, 110, 148},
        good_solution = {8, 3, 2},
        solution;
    
      BOOST_CHECK_NO_THROW(
        solution = cramer_solving(matrix, free_term_column, size)
      );
    
      BOOST_REQUIRE_EQUAL(solution.size(), size);
      for (int i = 0; i < size; ++i) {
        BOOST_REQUIRE_CLOSE(solution[i], good_solution[i], Accuracy);
      }
    }
    
    BOOST_AUTO_TEST_CASE(CramerSolving_NoSolution) {
      const int size = 2;
      std::vector<std::vector<double> >
        matrix = {{1,2}, {4,8}};
      std::vector<double>
        free_term_column = {3,6};
    
      BOOST_CHECK_THROW(cramer_solving(matrix, free_term_column, size),
                        NoSolution);
    }

    Подробнее про назначение модульных тестов и их разработку смотрите в статье: “Юнит-тестирование. Пример. Boost Unit Test“.

    Разработка через тестирование (TDD) рекомендует нам написать сейчас заглушку функции и убедиться что тесты работают (вызываются и проваливаются):

    template <typename T>
    std::vector<T> cramer_solving(std::vector<std::vector<T> > &matrix,
                                  std::vector<T> &free_term_column, int n) {
      std::vector<T> solution;
      return solution;
    }

    Остается закодировать алгоритм. Напомню, он заключается в вычислении главного определителя, а затем вычислению n дополнительных определителей (для матриц, полученных заменой i-того столбца на столбец свободных членов). Корни получаются в результате деления дополнительного определителя на главный. При этом если главный определитель равен нулю – то система не имеет решения:

    template <typename T>
    std::vector<T> cramer_solving(std::vector<std::vector<T> > &matrix,
                                  std::vector<T> &free_term_column, int n) {
      T mainDet = gauss_determinant(matrix, n);
      if (std::abs(mainDet) < 0.0001)
        throw NoSolution();
      std::vector<T> solution(n);
      for (int i = 0; i < n; ++i) {
        swap_column(matrix, free_term_column, i, n);
        solution[i] = gauss_determinant(matrix, n) / mainDet;
        swap_column(matrix, free_term_column, i, n);
      }
      return solution;
    }
    

    В данном случае использовался метод Гаусса вычисления определителя. Подставив такой код в программу запустим еще раз тесты, получим следующий ответ системы:

    Running 4 test cases…

    *** No errors detected

Для ответа в этой теме необходимо авторизоваться.