Разработка приложения решения системы линейных алгебраических уравнений методом Гаусса
Условие задачи
Задана система линейных алгебраических уравнений:
Разработать приложение, которое осуществляет решение системы линейных алгебраических уравнений с помощью метода Гаусса. Работа приложения должна быть реализована в виде мастера, в котором информация для каждого следующего шага определяется из информации на предшествующем шаге.
Выполнение
1. Загрузить Borland C++ Builder.
Сохранить проект.
При сохранении проекта имя модуля главной формы приложения оставляем по умолчанию «Unit1.cpp«.
Рис. 1. Форма приложения с созданными файлами
2. Разработка главной формы приложения
2.1. Название приложения
Задать название приложения. Для этого свойство Caption главной формы устанавливаем в значение «Метод Гаусса».
2.2. Установка свойств формы
Выделить форму. В Object Inspector установить значение следующих свойств:
– свойство Border Style = bsDialog;
– свойство Position = poScreenCenter;
– в свойстве Font выбрать параметры шрифта: шрифт Tahoma, размер шрифта 12 (рис. 2).
Рис. 2. Установка параметров шрифта главной формы приложения
В результате, форма приложения примет вид как показано на рисунке 3.
Рис. 3. Главная форма приложения
2.3. Компонент типа TGroupBox
Размещаем на форме компонент (элемент управления) типа TGroupBox из палитры компонент «Tool Palette«.
Рис. 4. Компонент типа TGroupBox
В результате, система создаст объект-переменную с именем GroupBox1.
Изменяем размеры компонента GroupBox1 на всю ширину окна главной формы.
Свойство Caption компонента GroupBox1 устанавливаем в значение «Условие задачи«. Форма приложения будет иметь вид, как показано на рисунке 5.
Рис. 5. Форма приложения после размещения компонента TGroupBox
2.4. Компонент типа TLabel.
Размещаем компонент типа TLabel в области компонента TGroupBox. Автоматически создается объект-переменная с именем Label1 (рис. 6).
Устанавливаем свойство WordWrap компонента Label1 в значение «true» (рис. 6).
С помощью мышки изменяем ширину вывода текста компонента Label1 (рис. 6).
Рис. 6. Компонент Label1, свойство WordWrap
Свойство Caption компонента Label1 устанавливаем в значение:
Решить систему линейных алгебраических уравнений методом Гаусса
В результате, форма приложения примет вид, как показано на рисунке 7.
Рис. 7. Форма приложения после размещения компонента Label1
2.5. Компоненты типа TButton.
Размещаем на форме компоненты типа TButton. В результате образуются два объекта-переменные с именами Button1 и Button2.
Для лучшей наглядности изменяем размеры компонент так как показано на рисунке 8.
Рис. 8. Форма приложения с размещенными компонентами Button1 и Button2
Устанавливаем такие свойства компонент Button1 и Button2:
– в компоненте Button1 свойство Caption = «Выход»;
– в компоненте Button2 свойство Caption = «Расчет >>».
В результате форма приложения примет вид, как показано на рисунке 9.
Рис. 9. Главная форма приложения после размещения всех компонент
3. Программирование события клика на кнопке «Выход».
Вызовем событие OnClick компонента Button1 (кнопка «Выход«) (рис. 10). Событие размещается на вкладыше Events в Object Inspector.
Процесс программирования события OnClick подробно описан здесь.
Рис. 10. Вызов события OnClick компонента Button1
В результате, откроется окно с программным кодом метода обработки события. Между скобками { } вводим вызов метода Close().
Метод Close() закрывает окно главной формы приложения и осуществляет все необходимые операции по освобождению памяти, ресурсов и т.д.
Листинг метода обработки события следующий:
void __fastcall TForm1::Button1Click(TObject *Sender) { Close(); }
4. Разработка формы ввода числа уравнений n.
4.1. Размещение компонент на форме и их настройка.
Процесс создания новой формы подробно описан здесь.
Для создания новой формы вызовем команду
File -> New -> Form C++ Builder
В результате, будет создана новая форма, как показано на рисунке 11. Сохраняем форму под именем «Unit2.cpp«.
Создаются файлы, которые соответствуют форме:
– файл «Unit2.h«, содержащий описания глобальных переменных и подключения других модулей;
– файл «Unit2.cpp«, содержащий реализацию методов формы;
– файл «Unit2.dfm«, содержащий описание изображения формы на экране (размеры окна, координаты формы относительно окна экрана, значение цветов и прочее).
Новосозданной форме отвечает объект с именем Form2. С помощью этого имени можно приступаться к свойствам и методам формы Form2.
Рис. 11. Новосозданная форма Form2
Осуществим настройку формы Form2.
Сначала настроим свойства формы:
– свойство Caption = «Задайте число уравнений»;
– свойство BorderStyle = bsDialog;
– свойство Position = poScreenCenter;
– в свойстве Font нужно выбрать следдующие параметры шрифта: шрифт Tahoma, размер шрифта 12.
Размещаем на форме такие компоненты:
– компонент типа TGroupBox которому будет отвечать объект GroupBox1;
– компонент типа TLabel, размещается внутри области компонента GroupBox1. Компоненту типа TLabel отвечает объект-переменная Label1;
– компонент типа TEdit, размещается внутри области компонента GroupBox1. Этому компоненту отвечает объект (переменная) Edit1;
– два компонента типа TButton, которым отвечают объекты с именами Button1 и Button2.
Осуществим настройку свойств компонент:
– в компоненте GroupBox1 значение свойства Caption = «» (пустая строка);
– в компоненте Label1 значение свойства Caption = «n = «;
– в компоненте Edit1 значение свойства Text = «»;
– в компоненте Button1 значение свойства Caption = «<< Назад»;
– в компоненте Button2 значение свойства Caption = «Далее >>».
После размещения компонент и корректирования размеров формы, форма Form2 имеет вид как показано на рисунке 12.
Рис. 12. Форма Form2 после размещения и настройки всех компонент
4.2. Программирование обработчиков событий формы Form2.
В форме Form2 программируем два обработчика событий:
– обработчик события OnClick клика на кнопке «<< Назад«;
– обработчик события OnClick клика на кнопке «Далее >>«.
Листинг обработчика события клика на кнопке Button1 («<< Назад«):
void __fastcall TForm2::Button1Click(TObject *Sender) { ModalResult = mrNo; }
Листинг обработчика события клика на кнопке Button2 («Продолжить >>«):
void __fastcall TForm2::Button2Click(TObject *Sender) { ModalResult = mrOk; }
Глобальная переменная ModalResult отвечает за состояние формы. Если глобальная переменная ModalResult=0, то это означает что форма открытая как модальное окно. Как только значение ModalResult станет ненулевым, то форма Form2 закроется с кодом возврата, помещенным в ModalResult.
Таким образом, если пользователь сделает клик на кнопке Button1, то форма Form2 закроется с кодом возврата mrNo. Если пользователь сделает клик на кнопке Button2, то форма Form2 закроется с кодом возврата mrOk.
5. Построение формы ввода коэффициентов в уравнениях.
5.1. Размещение компонент на форме и их настройка.
Создание формы происходит стандартным путем и описано в п. 4.
Сохраняем форму под именем предлагаемым по умолчанию «Unit3.cpp«.
После создания формы получим объект с именем Form3. С помощью этого объекта можно будет использовать методы и свойства формы Form3.
Данной форме отвечают файлы с именами «Unit3.h«, «Unit3.cpp» и «Unit3.dfm«.
Сначала осуществим настройку свойств формы Form3 так, как описано в п. 4:
– свойство Caption = «Ввод коэффициентов уравнений«;
– свойство BorderStyle = bsDialog;
– свойство Position = poScreenCenter;
– в свойстве Font нужно выбрать параметры шрифта: шрифт Tahoma, размер шрифта 12.
Для построения формы ввода коэффициентов уравнений используем такие компоненты:
– два компонента типа TLabel. Автоматически будут созданы объекты с такими именами: label1 и label2;
– компонент типа TStringGrid (рис. 13) для ввода коэффициентов, которые размещаются в левой части системы уравнений.
Компонент TStringGrid размещается во вкладке Additional панели инструментов «Tool Palette«. Создается объект с именем StringGrid1;
– компонент типа TStringGrid (рис. 13) для введения коэффициентов, которые размещаются в правой части системы уравнений. Создается объект с именем StringGrid2;
– два компонента типа TButton (кнопки «<< Назад» и «Продолжить >>«). Создаются два объекта с именами Button1 и Button2.
Рис. 13. Компонент TStringGrid на палитре компонент
После размещения компонент и корректировки их размеров, форма Form3 будет иметь приблизительно следующий вид (рис. 14).
Рис. 14. Форма Form3
Формируем свойства компонент формы Form3:
– в компоненте Label1 свойство Caption = «Коэффициенты в левой части уравнения«;
– в компоненте Label2 свойство Caption = «Правая часть»;
– в компоненте Button1 свойство Caption = «<< Назад»;
– в компоненте Button2 свойство Caption = «Далее >>».
Формируем свойства компонентов типа TStringGrid:
– в компоненте StringGrid1 свойство FixedCols = 0 (число фиксированных колонок);
– в компоненте StringGrid1 свойство FixedRows = 0 (число фиксированных строк);
– в компоненте StringGrid2 свойство FixedCols = 0;
– в компоненте StringGrid2 свойство FixedRows = 0;
– в компоненте StringGrid1 выбираем вкладку Options и устанавливаем опцию goEditing в значение «true«;
– в компоненте StringGrid2 во вкладке Options опция goEditing = «true«.
Рис. 15. Установление опции goEditing во вкладке Options компонента StringGrid1
После выполненных действий, форма Form3 будет иметь вид как показано на рисунке 16.
Рис. 16. Форма Form3 после окончательного формирования
5.2. Программирование обработчиков событий формы Form3.
Программируем обработчики событий OnClick клика на кнопках Button1 и Button2 формы Form3.
Листинг обработчиков событий приведен ниже.
// кнопка "<< Назад" void __fastcall TForm3::Button1Click(TObject *Sender) { ModalResult = mrNo; } // кнопка "Далее >>" void __fastcall TForm3::Button2Click(TObject *Sender) { ModalResult = mrOk; }
6. Создание формы вывода результата.
Последней в приложении создается форма, которая будет выводить результат вычислений. Процесс создания и сохранения формы подробно описан здесь. При сохранении формы оставляем имя по умолчанию «Unit4.cpp«.
В результате получаем объект с именем Form4.
Новосозданная форма Form4 описывается в файле «Unit4.dfm«. Также форме отвечают файлы «Unit4.h» и «Unit4.cpp«.
6.1. Построение формы Form4.
Сначала настраиваем свойства формы Form4:
– свойство Caption = «Результат»;
– свойство BorderStyle = bsDialog;
– свойство Position = poScreenCenter;
– в свойстве Font нужно выбрать следующие параметры шрифта: шрифт Tahoma, размер шрифта 12.
Также корректируем размеры формы.
Следующим шагом идет размещение на форме компонент.
Размещаем на форме следующие компоненты (рис. 17):
– один компонент типа TLabel;
– два компонента типа TStringGrid;
– один компонент типа TButton.
Корректируем размеры и позиции компонент для удобного отображения.
После размещения компонент будут созданы объекты с такими именами: Label1, StringGrid1, StringGrid2, Button1. В компоненте StringGrid1 выводятся номера переменных величин x в уравнении. В компоненте StringGrid2 выводятся значения решения системы уравнений.
Настраиваем компоненты формы следующим образом:
– в компоненте Label1 свойство Caption = «Решение системы»;
– в компоненте Button1 свойство Caption = «OK»;
– в компоненте StringGrid1 свойства FixedCols = 0 и FixedRows = 0;
– в компоненте StringGrid2 свойства FixedCols = 0 и FixedRows = 0.
После размещения и настройки компонент, форма Form4 будет иметь вид, как показано на рисунке 17.
Рис. 17. Форма Form4 после окончательного формирования
6.2. Программирование события клика на кнопке «ОК» формы Form4.
Листинг обработчика события клика на кнопке «ОК» следующий:
void __fastcall TForm4::Button1Click(TObject *Sender) { ModalResult = mrOk; }
7. Написание программного кода расчета.
7.1. Подключение модулей «Unit2.h», «Unit3.h», «Unit4.h» к модулю «Unit1.h».
Для того, чтобы из главной формы приложения Form1 вызвать второстепенные формы, нужно осуществить их подключения в модуле «Unit1.h«.
Подключение модулей форм Form2, Form3, Form4 к форме Form1 осуществляется стандартным для языка C/C++ способом.
Сначала нужно перейти в модуль «Unit1.h«.
Затем после строк
#ifndef Unit1H #define Unit1H //------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp>
нужно ввести такой текст:
#include "Unit2.h" #include "Unit3.h" #include "Unit4.h"
7.2. Ввод переменных и констант в модуль «Unit1.h»
С помощью Project Manager переходим в модуль «Unit.h«.
Сначала вводим константу Max, которая обозначает максимально допустимое количество уравнений. Для этого, после строк
... #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "Unit2.h" #include "Unit3.h" #include "Unit4.h"
вводим текст
#define Max 20
В раздел private класса TForm1 формы вводим внутренние переменные:
– n – количество уравнений;
– A – двумерный массив размером n*(n+1) коэффициентов при переменных в уравнениях;
– X – одномерный массив решений уравнений;
– переменная целого типа f_not, которая обозначает наличие или отсутствие решения в системе уравнений.
Также в раздел public вводим функцию Calc(), которая непосредственно будет осуществлять расчет по методу Гаусса.
В общем, описание класса в модуле Unit1.h выглядит следующим образом:
... class TForm1 : public TForm { __published: // IDE-managed Components TGroupBox *GroupBox1; TLabel *Label1; TButton *Button1; TButton *Button2; void __fastcall Button1Click(TObject *Sender); private: // User declarations int n; // число уравнений float A[Max][Max+1]; // матрица коэффициентов float X[Max]; // массив bool f_not; // true-система не определена, false - есть решение public: // User declarations __fastcall TForm1(TComponent* Owner); int Calc(void); // функция расчета по методу Гаусса }; ...
7.3. Написание функции Calc() решения системы уравнений по методу Гаусса.
С помощью Project Manager переходим в файл «Unit1.cpp«.
В файле «Unit1.cpp» вводим текст реализации функции Calc(), объявленной в модуле «Unit1.h«.
Функция Calc() возвращает 0, если система уравнений не определена. В другом случае возвращается значение 1.
Листинг метода Calc() без объяснений подробностей алгоритма следующий:
int TForm1::Calc(void) { int u,k,m,i,j; int f_exit; float t; u = 0; f_not = false; while (u!=n) { u++; k=u; while (A[k][u]==0) { k++; if (k>n) { f_not = true; // система не определена return 0; } } if (k!=u) { for (m = u; m<=n+1; m++) { t = A[u][m]; A[u][m] = A[k][m]; A[k][m] = t; } } for (j = n+1; j >= u; j--) A[u][j] = A[u][j]/A[u][u]; m = n + 1; if ((k+1)<=n) for (i = k+1; i <= n; i++) for (j = u+1; j <= m; j++) A[i][j] = A[i][j]-A[i][u] * A[u][j]; } // Построение массива результатов for (i = n; i >= 1; i--) { X[i] = A[i][m]; if (i!=1) for (k = i-1; k>=1; k--) A[k][m] = A[k][m] - A[k][i] * X[i]; } return 1; // есть решение }
7.4. Программирование события клика на кнопке «Расчет».
Листинг обработчика события клика на кнопке «Расчет» (Button2) следующий:
void __fastcall TForm1::Button2Click(TObject *Sender) { int i, j, res; Form1->Visible = false; // прячем форму if (Form2->ShowModal()==mrOk) // вывод формы ввода числа уравнений n { n = StrToInt(Form2->Edit1->Text); // взяли число уравнений Form3->StringGrid1->ColCount = n; // построение матрицы - количество колонок Form3->StringGrid1->RowCount = n; // количество строк матрицы Form3->StringGrid2->RowCount = n; // правая часть Form3->StringGrid2->ColCount = 1; // построение формы вывода результата Form4->StringGrid1->RowCount = n; Form4->StringGrid1->ColCount = 1; Form4->StringGrid2->RowCount = n; Form4->StringGrid2->ColCount = 1; for (i = 1; i <= n; i++) Form4->StringGrid1->Cells[0][i-1] = "X[" + IntToStr(i) + "]="; if (Form3->ShowModal()==mrOk) // вывод формы ввода данных { // Построение матрицы A for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) A[i][j] = StrToFloat(Form3->StringGrid1->Cells[j-1][i-1]); // столбик B for (i = 1; i <= n; i++) A[i][n+1] = StrToFloat(Form3->StringGrid2->Cells[0][i-1]); Calc(); if (!f_not) { // Формирование массива X - результатов // внесение результата в форму Form4 for (i=1; i<=n; i++) Form4->StringGrid2->Cells[0][i-1] = FloatToStrF(X[i],ffFixed,8,2); Form4->ShowModal(); // вывод формы результата } else MessageDlg("Система не определена!", mtConfirmation, TMsgDlgButtons() << mbOK, 0); } } Form1->Visible = true; }
Объясним некоторые фрагменты кода. Вывод формы происходит с помощью функции ShowModal(). Преобразование целого типа в строку реализуется функцией IntToStr().
Преобразование из строки в соответствующий действительный тип реализован функцией StrToFloat().
Преобразование из соответствующего действительного типа в строку происходит с помощью функции FloatToStr().
Для вывода сообщения о неопределенности системы уравнений используется функция MessageDlg().