Решение СЛАУ методом Зейделя
Автор: Sysaninмарта 18
Продолжим (метод Гаусса) решать системы линейных алгеброических выржений (СЛАУ) разными способами. Сегодня представлю вам класс для вычисления СЛАУ по методу Зейделя (основан на простой итерации).
Кому интересно математическое обоснвание прошу сюда. Остальным расскажу основную суть: предполагаем, что все корни уравнения равны некоторым определенным числам (решая программно проще взять равными нулю). Далее будем последовательно находить корни уравнений, причем только что найденным коренем будем заменять сответствующий корень принятый или найденный ранее. Когда найдем все корни вычислим погрешность. Если она будет больше допустимой, то повторяем цикл, только в качестве начальных корней будем использовать наденные.
Этот метод можно использовать для небольшого количества матриц. А точнее которые имеют преобладание главной диагонали. Сам класс не проверяет корректность матрицы. Поэтому в случае не корректной вернет переменные, со значениями превышающими допустимые для переменных.
double *x, // x
*b, // b (свободные члены)
tochnost; // точность измерения
double **mas; // коэфиценты
int razmer; // размер матрицы
public:
zedel(int razm, double toch);
~zedel();
zedel(zedel &temp); // констурктор копий
void write_to_mass(int y, int x, double value); //запись элемента в массив
void write_to_b(int n, double value); //запись элемента в b
void resit(); // решать систему
double* get_result(); // получить ответы, возращается массив указазателей на Х
double get_result(int n); // получить указанный в качестве аргумента Х
};
zedel::zedel(int razm, double toch){
razmer=razm;
tochnost=toch;
//выделяем память
x = new double[razmer];
b = new double[razmer];
mas = new double*[razmer];
for(int i=0; i < razmer; i++) mas[i] = new double[razmer];
}
zedel::zedel(zedel &temp){
razmer=temp.razmer;
tochnost=temp.tochnost;
//выделяем память
x = new double[razmer];
b = new double[razmer];
mas = new double*[razmer];
for(int i=0; i < razmer; i++) mas[i] = new double[razmer];
}
zedel::~zedel(){
//очищаем память
delete[] x;
delete[] b;
delete[] mas;
}
//запись элемента в массив
void zedel::write_to_mass(int y, int x, double value){
mas[y][x]=value;
}
// запись в b
void zedel::write_to_b(int n, double value){
b[n]=value;
}
// получить ответы, возращается массив указазателей на Х
double* zedel::get_result(){
return x;
}
// получить указанный в качестве аргумента Х
double zedel::get_result(int n){
return x[n];
}
// решаем систему
void zedel::resit(){
//Предположим, что все Х=0
for(int i=0; i < razmer; i++) x[i]=0;
double max=0; // макс погрешность в данной итерации
// делаем итерации, пока погрешность не будет меньше допустимой
do{
max=0;
// считаем каждый Х
for(int i=0; i < razmer; i++){
double sum=0; // сумма всех остальных иксов с коэфицентами, кроме i-го
// считаем сумму Х с коэфицентами кроме i-го
for(int k=0; k < razmer; k++){
if(k!=i) sum+=mas[i][k]*x[k];
}
double temp=(b[i]-sum)/mas[i][i];
//считаем погрешность
if(fabs(temp-x[i]) > max) max=fabs(temp-x[i]);
x[i] = temp;
}
}while(max>tochnost);
}
Вот так работать с классом:
//второй точность подсчета
zedel zed(razmer, toch);
//так заполняем массив коэфицентов
//первый аргумент- номер строки
//второй - номер столбца
//третий - значение
zed.write_to_mass(i, j, temp);
//заполняем свободные члены b, первый аргумент - номер члена
//второй - значение
zed.write_to_b(j, temp);
//высчитать корни
zed.resit();
//получить i-ый корень
double x=zed.get_result(i);
//получить указатель на массив корней
double *x=zed.get_result();
P.S. этот метод имеет в основном обучающую суть. Для практического использования он имеет смысл только для очень больших матриц с преобладанием главной диоганали, так как для такого случая имеют высокую скорость работы, по сравнению с другими.
Нет комментариев