Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

  // обнуляя элементы, стоящие ниже диагонали:

  for (Index j = 0; j

    const double pivot = A(j, j);

    if (pivot == 0) throw Elim_failure(j);

    // обнуляем элементы, стоящие ниже диагонали в строке i

    for (Index i = j+1; i

      const double mult = A(i, j) / pivot;

      A[i].slice(j) = scale_and_add(A[j].slice(j),

      –mult, A[i].slice(j));

      b(i) –= mult * b(j); // изменяем вектор b

    }

  }

}

Опорным называется элемент, лежащий на диагонали в строке, которую мы в данный момент обрабатываем. Он должен быть ненулевым, потому что нам придется на него делить; если он равен нулю, то генерируется исключение.

Vector back_substitution(const Matrix& A, const Vector& b)

{

  const Index n = A.dim1;

  Vector x(n);

  for (Index i = n – 1; i >= 0; ––i) {

    double s = b(i)–dot_product(A[i].slice(i+1),x.slice(i+1));

    if (double m = A(i, i))

      x(i) = s / m;

    else

      throw Back_subst_failure(i);

  }

  return x;

<p id="AutBody_Root474"><strong>24.6.2. Выбор ведущего элемента</strong></p>

Для того чтобы избежать проблем с нулевыми диагональными элементами и повысить устойчивость алгоритма, можно переставить строки так, чтобы нули и малые величины на диагонали не стояли. Говоря “повысить устойчивость”, мы имеем в виду понижение чувствительности к ошибкам округления. Однако по мере выполнения алгоритма элементы матрицы будут изменяться, поэтому перестановку строк приходится делать постоянно (иначе говоря, мы не можем лишь один раз переупорядочить матрицу, а затем применить классический алгоритм).

void elim_with_partial_pivot(Matrix& A, Vector& b)

{

  const Index n = A.dim1;

  for (Index j = 0; j < n; ++j) {

    Index pivot_row = j;

    // ищем подходящий опорный элемент:

    for (Index k = j + 1; k < n; ++k)

      if (abs(A(k, j)) > abs(A(pivot_row, j))) pivot_row = k;

    // переставляем строки, если найдется лучший опорный

    // элемент

    if (pivot_row != j) {

      A.swap_rows(j, pivot_row);

      std::swap(b(j), b(pivot_row));

    }

    // исключение:

    for (Index i = j + 1; i < n; ++i) {

      const double pivot = A(j, j);

      if (pivot==0) error("Решения нет: pivot==0");

        onst double mult = A(i, j)/pivot;

      A[i].slice(j) = scale_and_add(A[j].slice(j),

      –mult, A[i].slice(j));

      b(i) –= mult * b(j);

    }

  }

}

Для того чтобы не писать циклы явно и привести код в более традиционный вид, мы используем функции swap_rows и scale_and_multiply.

<p id="AutBody_Root475"><strong>24.6.3. Тестирование</strong></p>

Очевидно, что мы должны протестировать нашу программу. К счастью, это сделать несложно.

void solve_random_system(Index n)

{

  Matrix A = random_matrix(n); // см. раздел 24.7

  Vector b = random_vector(n);

  cout << "A = " << A << endl;

  cout << "b = " << b << endl;

  try {

    Vector x = classical_gaussian_elimination(A, b);

    cout << "Решение методом Гаусса x = " << x << endl;

    Vector v = A * x;

    cout << " A * x = " << v << endl;

  }

  catch(const exception& e) {

    cerr << e.what << std::endl;

  }

}

Существуют три причины, из-за которых можно попасть в раздел catch.

• Ошибка в программе (однако, будучи оптимистами, будем считать, что этого никогда не произойдет).

• Входные данные, приводящие к краху алгоритма classical_elimination (целесообразно использовать функцию elim_with_partial_pivot).

• Ошибки округления.

Тем не менее наш тест не настолько реалистичен, как мы думали, поскольку случайные матрицы вряд ли вызовут проблемы с алгоритмом classical_elimination.

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программирование. Принципы и практика использования C++ Исправленное издание
Программирование. Принципы и практика использования C++ Исправленное издание

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова

Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT