Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основная книга по С++й.doc
Скачиваний:
16
Добавлен:
28.10.2018
Размер:
2.07 Mб
Скачать

Void lu_backsub (double **a, int n, int *indx, double *b)

{

register int i, j, ip, ii = -1;

double sum;

/* первый шаг обратной замены */

for (i = 0; i < n; i++)

{

ip = indx[i];

sum = b[ip];

b[ip] = b[i];

if (ii >= 0)

for (j = ii; j < i; j++) sum -= a[i][j] * b[j];

else if (sum) ii = i; /* получен ненулевой элемент */

b[i] = sum;

}

/* второй шаг */

for (i = n - 1; i >= 0; i--)

{

sum = b[i];

for (j = i + 1; j < n; j++) sum -= a[i][j] * b[j];

b[i] = sum / a[i][i];

}

}

/* инвертирование матрицы */

Void lu_invert (double **a, int n, int *indx, double **inv, double *col)

{

register int i, j;

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

{

for (i = 0; i < n; i++) col[i] = 0.;

col[j] = 1.;

LU_backsub (a, n, indx, col);

for (i = 0; i < n; i++) inv[i][j] = col[i];

}

}

/* определяющее вычисление*/

double LU_determ (double **a, int n, int *indx, int *d)

{

register int j;

double res = (double)(*d);

for (j = 0; j < n; j++) res *= a[j][j];

return (res);

}

Пример 15. Алгоритм поиска интервала нахождения корня нелинейной функции.

Выяснение интервала, на котором корень содержится является важной проблемой поиска корня нелинейной функции действительной переменной. Здесь приведен алгоритм поиска такого интервала и ограничения на его применение. Примем, что корень функции f(x) окружен на интервале [a,b], если f(a) и f(b) имеют противоположные знаки. Чтобы окруженный согласно этому определению корень действительно существовал на этом интервале, достаточно непрерывности f(x), а для его единственности  еще и монотонности. При невыполнении этих свойств возможно отсутствие корня на [a,b] или неопределенность его позиции.

При использовании компьютера, всегда имеем дело с дискретным набором возможных представлений чисел (хотя и достаточно плотным). Кроме того, монотонность вычисленной функции может быть слегка нарушена в пределах точности ее вычисления. Это в ряде случаев усложняет вычисление окруженных корней функции, если к их точности предъявляются завышенные требования.

Окружение корня функции при гарантии ее определения на неограниченном интервале, производится по следующему итерационному алгоритму.

  1. Для начального приближения x0, найти f0=f(x0), задать начальный интервал поиска D и его инкремент d>1.

  2. Вычислить a=x0-D, b=x0+D; fa=f(a), fb=f(b).

  3. Увеличить интервал поиска: D=D*d. Если интервал превысил некоторый заданный предел, то выйти с индикацией ошибки.

  1. Если знаки fa и f0 отличаются, то считать корень окруженным на [a,x0] > выход.

  2. Если знаки fb и f0 отличаются, то считать корень окруженным на [x0,b] -> выход.

  3. Если f0 > 0 (случай меньше нуля делается аналогично) алгоритм продолжается:

  1. Проверяется, какое из fa или fb наименьшее. Если оба одинаковы, то переходим к 4a (двусторонний поиск), если fb  производим поиск вправо 4b, иначе  поиск влево 4c.

  1. Находим a=a-D, b=b+D, fa=f(a), fb=f(b), идем к пункту 3.

  2. Присваиваем последовательно a=x0, x0=b, fa=f0, f0=fb; находим b=b+D, fb=f(b), идем к пункту 3.

  3. Аналогично 4b, только направление поиска  влево.

Так как интервал поиска постоянно расширяется, то в конце концов используя указанный алгоритм корень будет окружен. Возможны модификации алгоритма в двух направлениях:

  1. Увеличивать интервал не в геометрической прогрессии, а в арифметической либо по заданному сценарию;

  2. Если область определения функции заведомо ограничена, то расширение интервала поиска также следует ограничивать имеющимися пределами, либо доопределять функцию там, где ее оригинал не определен.

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <conio.h>

#include <string.h>

/*

Предполагается, что функция существует на бесконечном и непрерывном промежутке.