Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Программирование на Delphi


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный платный хостинг на базе Windows 2008

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Jimhucksly
Статус: 5-й класс
Рейтинг: 740
∙ повысить рейтинг »
Boriss
Статус: Академик
Рейтинг: 624
∙ повысить рейтинг »
Тимошенко Дмитрий
Статус: Студент
Рейтинг: 487
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / Delphi

Номер выпуска:1438
Дата выхода:30.09.2009, 14:30
Администратор рассылки:Калашников О.А., Руководитель
Подписчиков / экспертов:575 / 206
Вопросов / ответов:1 / 1

Вопрос № 172614: Здравствуйте, уважаемые Эксперты! Срочно нужна Ваша помощь! Для решения одной из моих задач мне нужно найти решение системы линейных уравнений методом Гаусса. Поискав в интернете нашел _один_ распространенный алгоритм (приведу ег...



Вопрос № 172614:

Здравствуйте, уважаемые Эксперты!

Срочно нужна Ваша помощь!

Для решения одной из моих задач мне нужно найти решение системы линейных уравнений методом Гаусса.

Поискав в интернете нашел _один_ распространенный алгоритм (приведу его ниже).
НО! Он работает только для матриц с ненулевыми значениями.

Я точно знаю, что методом Гаусса можно решить и с нулевыми, но такого примера не нашел.

Если у кого есть прошу поделитесь, пожалуйста. (Матрица n*n +значения). Т около 1000. приведенный ниже алгоритм для не нулевых значений нормально отрабатывается за 3 секунды.

P.S. Это не для курсовой и т.д.

Код:

unit Unit3;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Control s, Forms,
Dialogs, Grids, StdCtrls;

const MaxDimension = 10;

type

Vector = array[1..MaxDimension] of Double;
Matrix = array[1..MaxDimension] of Vector;

TForm3 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
StringGrid1: TStringGrid;
StringGrid2: TStringGrid;
Button1: TButton;
Label2: TLabel;
Label3: TLabel;
ListBox1: TListBox;
procedure Edit1Change(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var a: Matrix;
b,x: Vector;
h: Double;
i,j,k,n:integer;
begin
//Ввод данных
//Размерность системы
n := StrToIntDef(Text, StringGrid1.ColCount);
/ /Коэффициенты
for j := 0 to n - 1 do
for i := 0 to n - 1 do
a[i + 1, j + 1] := StrToFloatDef(StringGrid1.Cells[j, i], 0);
//Правая часть уравнения
for I := 0 to n - 1 do b[i + 1] := StrToFloatDef(StringGrid2.Cells[0, i], 0);
//Прямой ход - исключение переменных
for i:=1 to n-1 do
for j:=i+1 to n do
begin
a[j,i]:=-a[j,i]/a[i,i];
for k:=i+1 to n do
a[j,k]:=a[j,k]+a[j,i]*a[i,k];
b[j]:=b[j]+a[j,i]*b[i]
end;
x[n]:=b[n]/a[n,n]; //Деление на ноль
//Обратный ход - нахождение корней
for i:=n-1 downto 1 do
begin
h:=b[i];
for j:=i+1 to n do h:=h-x[j]*a[i,j];
x[i]:=h/a[i,i]
end;
//Вывод результата
for i:=1 to n do ListBox1.Items.Append('x(' + IntToStr(i) + ')=' + FloatToStr(x[i]));
end;

procedure TForm3.Edit1Change(Sender : TObject);
begin
with StringGrid1, Edit1 do
begin
ColCount := StrToIntDef(Text, 3);
RowCount := StrToIntDef(Text, 3);
end;
with StringGrid2, Edit1 do
RowCount := StrToIntDef(Text, 3)
end;

procedure TForm3.FormCreate(Sender: TObject);
var i, j: integer;
begin
//Заполнить коэф уравнения
Randomize;
for I := 0 to StrToIntDef(Text, StringGrid1.ColCount) - 1 do
for J := 0 to StrToIntDef(Text, StringGrid1.RowCount) - 1 do
StringGrid1.Cells[I, J] := IntToStr(Random(100));
for I := 0 to StrToIntDef(Text, StringGrid2.RowCount) - 1 do
StringGrid2.Cells[0, I] := IntToStr(Random(100))
end;

end.

Отправлен: 25.09.2009, 14:16
Вопрос задал: LanK, Профессионал
Всего ответов: 1
Страница вопроса »


Отвечает Сергей Бендер, 1-й класс :
Здравствуйте, LanK.


1) Непонятно, почему у тебя написано "Деление на ноль" в строчке с делением на a[n,n]. Оно, как правило, должно происходить раньше, в цикле при делении на a[i,i]

2) Напутано с алгоритмом - правильного ответа быть не должно. После
a[j,i]:=-a[j,i]/a[i,i];
надо делать такое же деление для b
b[j]:=-b[i]/a[i,i];

А строчка
b[j]:=b[j]+a[j,i]*b[i]
должна, во первых, находиться в цикле (у тебя нет begin end), во вторых, просчитывать k-й (а не j-й) элемент, т.е.:
b[k]:=b[k]+a[j,i]*b[k]

3) Обратный ход вполне можно делать от n:
for i:=n downto 1 do
а строчку
x[n]:=b[n]/a[n,n];
преспокойно стирать. Избыточна.

4) Теперь о нулевых диагональных элементах. Это нужен алгоритм с выбором столбцов. Собственно никакого особого алгоритма тут нет. Просто у системы можно без нарушения эквивалентности менять местами столбцы. Главное при это помнить какие столбцы переставлены.

Т.е. перед глав ным делением
a[j,i]:=-a[j,i]/a[i,i];
надо проверить a[i,i] на равнество нулю и, если да, то найти в строке какой-нибудь (например, первый) ненулевой. (Если все нули значит система недоопределени и не имеет единственного решения.) Это можно сделать сразу
m:=i;
while (a[i,m]<>0) and (m<=n) do inc(m);
if m>n then ... // все нули
Потом цикл по этим столбцам (от начала, а не от i)
for k:=1 to n do
begin
/// меняем местами a[i,k] и a[m,k]
end;

Останется только запоминть, какие элементы поменял. Это можно держать в массиве вроде
ind:array[1..n] of integer;
Перед прямым ходом надо его заполнить
for i:=1 to n do ind[i]:=i;
А результата выводить не как x[i], а как x[ind[i]].
(В принципе, может быть в Делфе уже есть какая-нибудь удобная штука для этого. Не помню.)

Удачи!

Ответ отправил: Сергей Бендер, 1-й класс
Ответ отправлен: 28.09.2009, 21:34

Оценка ответа: 5
Комментарий к оценке:
спасибо

Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 254815 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:
  • Вам помогли? Пожалуйста, поблагодарите эксперта за это!


    Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2009, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2009.6.9 от 25.09.2009

    В избранное