Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Метод Гаусса[c++] (https://forum.antichat.xyz/showthread.php?t=52608)

Ky3bMu4 02.11.2007 17:04

Методы Гаусса и Крамера[c++]
 
Как-то на кряклабе нашёл несколько примеров по решению систем линейных уравнений этим методом. Но 404. :( . Решил написать сам.
Для привидения матрицы к главному ступенчатому виду использовал метод ведущего элемента(для машины он проще чем сначала получение верхне треугольной матрицы , а потом самого вида.)
Т.к. часто попадаются "плохие" числа и приходится работать с дробями, то написал класс для дробей, перегрузил операторы *, / , + , - . Сделал функции 1, 2 и 3 элементарных преобразований.
Также есть алгоритм оброботки нулевых эллемтов на главной диагонале.Для этого написал отдельно класс для матриц.
Ввод матрицы осуществляется в самой программе. Программа таже показывает пошагово значения матриц.

Приводить весь алгоритм небуду, т.к. он очень большой. Исходники и откомпиленная прога ниже(вместе с Крамером):

http://slil.ru/25072002
http://ifolder.ru/4038710
http://rapidshare.com/files/68056699/Gauss_Kramer.rar.html

Ni0x 02.11.2007 20:09

Цитата:

сразу извиняюсь за свой ужасный английский
Ты бы лучше за свой ужасный С++ извинился. Что уж говорить, если ты не знаешь как через cout переменную вывести. Использовать код вида:
Код:

printf("Insert %d element of second matrix:",x);
cin>>temp;
cout<<"\r\n";

это норм по твоему? Но больше всего конечно порадовало подключение windows.h ради функции ExitProcess. Ты только не подумай, что я опять наезжаю на тебя или еще чего.

KEZ 02.11.2007 22:16

Ni0x, ты че, это кроссплатформеный Опен-Сурс от Кузьмича.
А вот это вообще будет висеть у меня на стенке в корридоре

Цитата:

void echo () const{
printf("%d/%d",chi,zn);
}
Ещё. Крутой деструктор
Цитата:

/*деструктор */
~drob() {}
)))))

Ну и самый прикол
Цитата:

drob::chi*mno.chi
на всякий случай кодер решил везде написать (по всему тексту прямо) "drob::" чтоб вдруг что....гыгы

Constantine 02.11.2007 22:38

Я лучше столбиком буду делить...

alextoun 02.11.2007 23:31

не удивительно, шо у меня ошибки при компеляци))
кстате я метод гаус на 5 сдал!!! имея 3 по математике в школе по жизни :)

.Slip 02.11.2007 23:43

Идея норм, сурс ужасен=\

Ky3bMu4 03.11.2007 16:42

Цитата:

не удивительно, шо у меня ошибки при компеляци))
Ну и какие-же это ошибки?

Цитата:

Что уж говорить, если ты не знаешь как через cout переменную вывести.
Так:
Код:

printf("Insert %d element of second matrix:",x);
Намного удобнее и короче, чем:
Код:

cout<<"Insert  "<<x<< " element of second matrix:";
Неправдали?

Ky3bMu4 07.11.2007 17:17

Большое спасибо за критику. Учёл.
Улучшил Гаусса, добавил обработку нулевых элементов на главной диагонале.

Вот, ещё написал метод Крамера с рекурсивным вычислением определителя.
Код:

#include <tchar.h>
#include <iostream>

using namespace std;

/*функция возведения в определённую степень числа -1*/
int mypow(int x){
        int y=1;
        for(int z=1;z<=x;z++){
  y*=-1;
        }
        return y;
}

/*класс матрица*/
class matrix{
public:

/*Конструктор: все элементы 0, размерность 0 */
 matrix(){
  size=0;
 
  for(int x=0;x<=100;x++)
          for(int y=0;y<=100;y++)
    m[x][y];
 }
/*Рекурсивная функция вычисления определителя */
 int GetDet(){
        int result=0;
  if(size==1){ //Если у матрицы размерность 2(математическая, С`шная 1), то вычисляем определитель
return m[0][0]*m[1][1]-m[0][1]*m[1][0];
  }
  else{
/*Вычисляем определитель путём вычёркивания строк и столбцов. Берём элементы из первой строки. */ 
  for(int x=0;x<=size;x++){
result+= mypow(x+2)*m[0][x]*(GetNew(x)).GetDet(); //рекурсия...
  }
  return result;
  }
        }

 /*Функия получения новой матрицы из старой, путём вычёркивания первой(нулевой) строки и х`овой колонки*/
 matrix GetNew(int st){
  matrix result;
  int z=0;
  result.size=size-1;

  for(int x=1;x<=size;x++){
  for(int y=0;y<=size;y++){
  if(y!=st){
  result.m[x-1][z]=m[x][y];
  z++;
  }
 
  }
  z=0;
  }
  return result;
 }

/*Функция вывода на экран квадратной матрицы*/
  void echo(void){
  for(int x=0;x<=size;x++){
    for(int y=0; y<=size;y++){
    cout<<m[x][y]<<" ";
    }
    cout<<"\r\n";
  }
  }
/*Функция вывода на экран матрицы-столбца */
  void echoEx(void){
    for(int x=0;x<=size;x++){
    cout<<m[x][0]<<"\r\n";
    }
  }

/*Функция установки размерности матрицы*/
  inline void SetSize(int r){
    size=r;
  }

/*Функция установки значения элемента*/
  inline void SetValue(int value, int x , int y){
    m[x][y]=value;
  }

  /*Функция замены колонки на матриуц-столбец*/
  inline void SetColumn(int column , matrix source){   
    for(int x=0;x<=size;x++){
    m[x][column]=source.m[x][0];
    }
  }
 
private:
        int m[100][100]; //сама матрица
        int size; //размерность
       
};
int _tmain(int argc, _TCHAR* argv[])
{
matrix first,second,temp; //наши матрицы
int element,size,maindet; //необходимые переменные
bool c=1; //для цикла
cout<<"The Kramer method for the system of linear equations. By Ky3bMu4 (c) 2007.\r\n\r\n";
while(c){
cout<<"\r\nInsert size of matrix:";
/*тут небольшая неровность: в математике матрица начинается с 1 столбцы, а в С - с 0-го  */
cin>>size;
first.SetSize(size);
second.SetSize(size);


/* вводим основную матрицу */
for(int x =0; x<=size; x++){
        for( int y=0; y<=size;y++){
  cout<<"\r\nInsert ["<<x<<";"<<y<<"] element of first matrix:";
  cin>>element;
  first.SetValue(element,x,y);
  }
}

/* вводим матрицу-столбец с числами*/
for(int x=0; x<=size; x++){
        cout<<"\r\nInsert "<<x<<" element of second matrix:";
        cin>>element;
        second.SetValue(element,x,0);
}
maindet = first.GetDet(); //вычисляем основной определитель(на него будем делить)
if(maindet!=0){
for(int x=0;x<=size;x++){ //кол-во элементов(переменных в линейном уравнении) == размерности главной матрицы.
//Заменяем колонку, вычисляем определитель , делим на главный определитель, пробуем сократить и выводим
temp = first;
temp.SetColumn(x,second); //заменянем колонку
cout<<"\r\nElement "<<x<<" = "<<temp.GetDet()<<"/"<<maindet; // выводим на экран       
}
}else{ //облом, главный определитель == 0, Крамер не прокатит :(((
        cout<<"\r\nSorry, but the main determinat of first matrix is 0.Stop.";
}

// The End
cout<<"\r\n\r\nFinish!";
cout<<"\r\nDo you want to again calculate new matrix(1/0)?:";
cin>>c;
}

        return 0;
}


Ссылка на откомпиленную прогу в первом посте.

ak[id] 07.11.2007 17:30

Спасибо, мы ща в уневере как раз ща решаем матрицы методом Гауса и Крамера.

GlOFF 07.11.2007 23:15

Да бред все это! Используйте метод Гаусаса.

~Lexx~ 08.11.2007 14:03

Блин я фигею дамы и господа. Вроде же была такая тема - там писали, что нельзя использовать рекурсию. Тут же приходиться вычислять n+1 определитель размером NxN. НИКТО не считает методом крамера, тем более рекурсивно.

Ky3bMu4 08.11.2007 22:25

Цитата:

НИКТО не считает методом крамера, тем более рекурсивно.
Кроме бедных студентов\продвинутых школьников на лабораторных...

Чуток подправил парсинг нулевых строк\нулевых элементов на главной диагонале. Теперь всегда корректно работать будет.

http://slil.ru/25077981

~Lexx~ 09.11.2007 03:09

Так объясните мне - если у нас есть метод гаусса - куда более эффективный и там не надо использовать рекурсию... Мот я чего не понимаю - это новая тенденция писать програму, которая жрет память и которую надо оптимизировать, вместо того, чтобы испольовать простейший алгоритм? попробуй вести у себя в алгоритме первую строку чтонить вроде одной десятитысячной, а остальные элементы - хотя бы вторая строка тысяч 35. а стальные эллементы дробные числа - и посмотри - точно ли у ьебя получаеться решение. Пы сы возьми матрицу хотя бы 250*250.

Ky3bMu4 09.11.2007 13:40

На практике, метод Крамера использовать действительно не имеет смысла, но дело в том, что его дают написать на лабораторных.

И на самом деле, с Крамером ещё хуже, чем кажеться: если понимать под 1 интерацией вычисление определителя матрицы 2х2, умножение его на число и складывание с чем-нибудь, то для вычисления определителя матрицы NxN нужно !N/2 таких интераций. Т.е. 17х17 - ~8кк таких интераций.

~Lexx~ 09.11.2007 13:59

прости - ты читал мое предпоследнее сообщение? И кстати раз уж ты так любишь считать - посчитай, сколько у тебя памяти уходит на рекурсию. - сколько ты лишних элементов хранишь. Я тут пониже создал тему - численные методы.
http://forum.antichat.ru/thread53080.html
тут только начало - но почитай - будет полезно.


Время: 23:09