Консультация № 180291
12.10.2010, 16:22
52.55 руб.
0 13 1
Здравствуйте, реализую программу для вычислений Систем Линейных Алгебраических Уравнений (СЛАУ) методами Гаусса и Вращения. (среда Visual C++ 2008, консолька).

Практически все реализовано (методы, проверки), но видимо куда-то закралась ошибка в методе Гаусса, либо алгоритм изначально неверен, и из-за этого не решает (по ходу ошибка находится в прямом ходе метода Гаусса, т.к. в методе вращения используется та-же функция, что и в обратном ходе гаусса, но там верно).

Эксперты, посмотрите исходничек, может вам удастся найти и устранить данную ошибку.

Пробовал например решать такую систему:

1x+2y = 3
2x+3y = 8

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

P.S еще нет исключений на те случаи, если данной СЛАУ не может существовать - может что и в этом посоветуете.

Полный код в архиве вот ссылка

Обсуждение

давно
Мастер-Эксперт
325460
1469
12.10.2010, 16:56
общий
у вас в исходнике в методе Гаусса не ведется работа с массивом ответов а его тоже нужно делить на выбранный элемент.
http://sources.codenet.ru/download/761/%D0%E5%F8%E5%ED%E8%E5_%F1%E8%F1%F2%E5%EC%FB_%EC%E5%F2%EE%E4%EE%EC_%C3%E0%F3%F1%F1%E0.html
посмотрите по этой ссылке решение, думаю это Вам поможет.
Об авторе:
to live is to die
Неизвестный
13.10.2010, 10:08
общий
cradlea:
Можете мой исходник поправить? С меня 2$ плюсом))
давно
Мастер-Эксперт
325460
1469
13.10.2010, 11:44
общий
дело в том что у Вас не переставляются строчки в методе Гаусса а только происходит операция с индексами и при выполнении обратного шага происходит деление на нуль. нужно переписать идея то у вас правильная но нужно переставлять массивы целиком.
да и поясните как вы понимаете запись A[_[Level]][Level] в чем отличие от A[Level][Level]
Об авторе:
to live is to die
давно
Академик
320937
2216
13.10.2010, 12:36
общий
cradlea:
Добрый день! Возьметесь?
давно
Мастер-Эксперт
325460
1469
13.10.2010, 12:45
общий
lamed:
сегодня не получится, завтра могу там нужно прямой ход переписать если у Вас готово решение то выкладывайте
мои решения под текст программы надо корректировать.
Об авторе:
to live is to die
Неизвестный
13.10.2010, 12:57
общий
Оп, оп. Вопрос решен! Ответ cradlea можно считать ответом, и стоимость вопроса присвоить ему.
давно
Мастер-Эксперт
325460
1469
13.10.2010, 13:03
общий
13.10.2010, 15:41
это ответ
Здравствуйте, crasher!

У вас в исходнике в методе Гаусса не ведется работа с массивом ответов а его тоже нужно делить на выбранный элемент.
URL >>
Посмотрите по этой ссылке решение, думаю это Вам поможет.

Дело в том что у Вас не переставляются строчки в методе Гаусса а только происходит операция с индексами и при выполнении обратного шага происходит деление на нуль. нужно переписать идея то у вас правильная но нужно переставлять массивы целиком.

В приложении пример, как можно поправить программу (решение не совсем красивое, но рабочее).
Так нужно вызывать его в программе:
Код:
void re_gauss(void)
{
system("cls");
reload();
if (flag>0)
{
GausResh(/**A,*B,Dim*/);

/* // Первый шаг.
for(int i = 0; i < Dim-1 ; i++)
{
Gauss1(i);

}
// Второй шаг.
for( i = Dim - 1; i >= 0; i--)
{
Gauss2(i);
}*/
flag=2;
metod=1;
cout<<"\r\nРешение методом Гаусса выполнено.\r\n\r\nНажмите любую кнопку для возврата в главное меню.";

}
else
{
system("color 0c");
cout<<"Наверное сначала нужно ввести данные, а потом считать.\r\nНажмите любую кнопку для возврата к меню. ";
}
getch();
}


Приложение:
void glavelem( int k, double mas[50][50], int n, int otv[] )
{
int i, j, i_max = k, j_max = k;
double temp;
//Ищем максимальный по модулю элемент
for ( i = k; i < n; i++ )
for ( j = k; j < n; j++ )
if ( fabs( mas[i_max] [j_max] ) < fabs( mas[i] [j] ) )
{
i_max = i;
j_max = j;
}
//Переставляем строки
for ( j = k; j < n + 1; j++ )
{
temp = mas[k] [j];
mas[k] [j] = mas[i_max] [j];
mas[i_max] [j] = temp;
}
//Переставляем столбцы
for ( i = 0; i < n; i++ )
{
temp = mas[i] [k];
mas[i] [k] = mas[i] [j_max];
mas[i] [j_max] = temp;
}
//Учитываем изменение порядка корней
i = otv[k];
otv[k] = otv[j_max];
otv[j_max] = i;
}




// переменные можно и не передавать
void GausResh(/*double * A, double *B, unsigned int razm*/)
{
// для простоты преобразовываем к одной матрице
double mas[50][50];// лучше перевести на указатели
int i,j,k;
int ot[50];
double prot[50];


// определяем массив
//для удобства
for(i=0;i<Dim;i++)
{
for (j=0;j<Dim;j++)
{
//*(mas+(i*Dim+1)+j)=A[i][j];
mas[i][j]=A[i][j];

}
mas[i][Dim]=B[i];
ot[i]=i;
}
// главный ход
for(k = 0; k < Dim ; k++)
{
glavelem(k,mas,Dim,ot);
for ( j = Dim; j >= k; j-- )
mas[k] [j] /= mas[k] [k];
for ( i = k + 1; i < Dim; i++ )
for ( j = Dim; j >= k; j-- )
mas[i] [j] -= mas[k] [j] * mas[i] [k];
}
// обратный ход
for ( i = 0; i < Dim; i++ )
X[i] = mas[i] [Dim];
for ( i = Dim - 2; i >= 0; i-- )
for ( j = i + 1; j < Dim-1; j++ )
X[i] -= X[j] * mas[i] [j];

// расстанавливаем значения икса в нужном порядке
// массив prot - массив решения
for ( i = 0; i < Dim; i++ )
for ( j = 0; j < Dim; j++ )
if ( i == ot[j] )
{ //Расставляем корни по порядку
prot[i]=X[j];
//break;
}

}
Об авторе:
to live is to die
давно
Академик
320937
2216
13.10.2010, 13:14
общий
cradlea:
Не спешите !!!!! Никто здесь не рвется в соревнование. Мой вопрос был связан с тем, что если Вы бы, к примеру, не взялись, то ответсвенность автоматически должны были бы брать на себя эксперты с более высоким статусом. Доделайте Вашу программу, выложите сначала в мини-форум, если проблем не будет, обратитесь к Модераторам с просьбой внести изменения в Ваш ответ. В ответ на код лучше выкладывать или код, или исправленную часть кода с комментариями. Будем с нетерпением ждать Вашего исходника :)
давно
Мастер-Эксперт
325460
1469
13.10.2010, 13:18
общий
lamed:
так исходник можно скачать по ссылке, там непосредственно метод Гаусса на С который нужно вставить в код программы задавшего вопрос.
Об авторе:
to live is to die
давно
Академик
320937
2216
13.10.2010, 13:21
общий
cradlea:
Все-таки есть смысл внести исправления в исходник автора, тем более, что Вы планировали это сделать :)
давно
Мастер-Эксперт
325460
1469
13.10.2010, 13:30
общий
нет проблем, напишу функцию.
выложу тут. чуть позднее будет.
Об авторе:
to live is to die
давно
Мастер-Эксперт
325460
1469
13.10.2010, 15:23
общий
void glavelem( int k, double mas[50][50], int n, int otv[] )
{
int i, j, i_max = k, j_max = k;
double temp;
//Ищем максимальный по модулю элемент
for ( i = k; i < n; i++ )
for ( j = k; j < n; j++ )
if ( fabs( mas[i_max] [j_max] ) < fabs( mas[i] [j] ) )
{
i_max = i;
j_max = j;
}
//Переставляем строки
for ( j = k; j < n + 1; j++ )
{
temp = mas[k] [j];
mas[k] [j] = mas[i_max] [j];
mas[i_max] [j] = temp;
}
//Переставляем столбцы
for ( i = 0; i < n; i++ )
{
temp = mas[i] [k];
mas[i] [k] = mas[i] [j_max];
mas[i] [j_max] = temp;
}
//Учитываем изменение порядка корней
i = otv[k];
otv[k] = otv[j_max];
otv[j_max] = i;
}




// переменные можно и не передавать
void GausResh(/*double * A, double *B, unsigned int razm*/)
{
// для простоты преобразовываем к одной матрице
double mas[50][50];// лучше перевести на указатели
int i,j,k;
int ot[50];
double prot[50];


// определяем массив
//для удобства
for(i=0;i<Dim;i++)
{
for (j=0;j<Dim;j++)
{
//*(mas+(i*Dim+1)+j)=A[i][j];
mas[i][j]=A[i][j];

}
mas[i][Dim]=B[i];
ot[i]=i;
}
// главный ход
for(k = 0; k < Dim ; k++)
{
glavelem(k,mas,Dim,ot);
for ( j = Dim; j >= k; j-- )
mas[k] [j] /= mas[k] [k];
for ( i = k + 1; i < Dim; i++ )
for ( j = Dim; j >= k; j-- )
mas[i] [j] -= mas[k] [j] * mas[i] [k];
}
// обратный ход
for ( i = 0; i < Dim; i++ )
X[i] = mas[i] [Dim];
for ( i = Dim - 2; i >= 0; i-- )
for ( j = i + 1; j < Dim-1; j++ )
X[i] -= X[j] * mas[i] [j];

// расстанавливаем значения икса в нужном порядке
// массив prot - массив решения
for ( i = 0; i < Dim; i++ )
for ( j = 0; j < Dim; j++ )
if ( i == ot[j] )
{ //Расставляем корни по порядку
prot[i]=X[j];
//break;
}

}




вот пример как можно поправить программу, решение не совсем красивое но рабочее
Об авторе:
to live is to die
давно
Мастер-Эксперт
325460
1469
13.10.2010, 15:24
общий
void re_gauss(void)
{
system("cls");
reload();
if (flag>0)
{
GausResh(/**A,*B,Dim*/);

/* // Первый шаг.
for(int i = 0; i < Dim-1 ; i++)
{
Gauss1(i);

}
// Второй шаг.
for( i = Dim - 1; i >= 0; i--)
{
Gauss2(i);
}*/
flag=2;
metod=1;
cout<<"\r\nРешение методом Гаусса выполнено.\r\n\r\nНажмите любую кнопку для возврата в главное меню.";

}
else
{
system("color 0c");
cout<<"Наверное сначала нужно ввести данные, а потом считать.\r\nНажмите любую кнопку для возврата к меню. ";
}
getch();
}




тут показано где его нужно вызывать в программе
Об авторе:
to live is to die
Форма ответа