Программа для решения дифференциальных уравнений первого порядка методом Рунге-Кутта

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИУКРАИНЫ
ГОСУДАРСТВЕННОЕ ВЫСШЕЕ УЧЕБНОЕЗАВЕДЕНИЕ
УКРАИНСКИЙ ГОСУДАРСТВЕННЫЙ
ХИМИКО-ТЕХНОЛОГИЧЕСКИЙ УНИВЕРСИТЕТ
КАФЕДРА ИТК

КУРСОВАЯ РАБОТА
ПО КУРСУ
«ОБЪЕКТНО-ОРИЕНТИРОВАНОЕПРОГРАММИРОВАНИЕ»
ВЫПОЛНИЛ:
студент группы 3ИC27 Куделя С.В.
ПРОВЕРИЛ:
ассистент Ильхман Яна Викторовна
Днепропетровск 2009
 

СОДЕРЖАНИЕ
 
1.ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
2. ОПИСАНИЕПРЕДМЕТНОЙ ОБЛАСТИ (ПО)
2.1Назначение программного продукта
2.2 Основныезадачи
2.3 Входныеи выходные данные
3.ПРОЕКТИРОВАНИЕ
3.1 Выделениеосновных объектов ПО
3.2 Описание полей и методов
3.3 Иерархия классов на основевыделенных объектов
4. ОСНОВНЫЕ ФОРМЫ И КОМПОНЕНТЫ, ИСПОЛЬЗУЕМЫЕ ДЛЯ РЕАЛИЗАЦИИПРОГРАММЫ. ОСНОВНЫЕ АЛГОРИТМИЧЕСКИЕ РЕШЕНИЯ РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ
4.1 Метод Рунге-Кутта
4.2 Описаниепрограммы ” РЕШЕНИЕ ОДУ “
4.3Назначение элементов графического окна программы
4.4 Реакция программы при возникновении ошибок
4.5 Переченькомпонент DELPHI использованных в программе
5. ТЕХНИЧЕСКИЕХАРАКТЕРИСТИКИ И ТРЕБОВАНИЯ К ПО
6. ТЕКСТПРОГРАММЫ
7. РЕШЕНИЕДИФФЕРЕНЦИАЛЬНОГО УРАВНЕНИЯ Y = Y−2X/Y МЕТОДОМ РУНГЕ –КУТТА В СРЕДЕ EXCEL
ВЫВОД
 

1. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
Delphi являетсяобъектно-ориентированной средой программирования. В качестве языкапрограммирования используется язык Object Pascal.
Историческисложилось так, что программирование возникло и развивалось как процедурноепрограммирование, которое предполагает, что основой программы являетсяалгоритм, процедура обработки данных.
Объектно-ориентированное программирование(ООП) — это методика разработки программ, в основе которой лежит понятиеобъект. Объект — это некоторая структура, соответствующая объекту реальногомира, его поведению. Задача, решаемая с использованием методики ООП,описывается в терминах объектов и операций над ними, а программа при такомподходе представляет собой набор объектов и связей между ними. Объектно-ориентированноепрограммирование позволяет конструировать новые и производные (дочерние) классына основе существующих классов.
По сравнению страдиционными способами программирования ООП обладает рядом преимуществ.Главное из них заключается в том, что эта концепция в наибольшей степенисоответствует внутренней логике функционирования операционной системы (ОС)Windows. Программа, состоящая из отдельных объектов, отлично приспособлена креагированию на события, происходящие в ОС. К другим преимуществам ООП можноотнести большую надежность кода и возможность повторного использованияотработанных объектов.
Основные понятия ООПв языке Delphi: объект, класс, компонент;
Основные механизмыООП: инкапсуляция, наследование и полиморфизм;
Класс — помимо описания данных, включает описание процедур и функций, которыемогут быть выполнены над представителем класса — объектом. Данные классаназываются полями, процедуры и функции — методами. Переменные в зависимости отпредназначения именуются полями или свойствами.
При создании объекта он наследуетструктуру (переменные) и поведение (методы) своего класса.
Класс, называемый потомком, производным или дочерним классом (подклассом), также может быть создан на основедругого родительскогокласса (предка) и приэтом наследует его структуру и поведение.
Методы — этопроцедуры и функции, описанные внутри класса и предназначенные для операций надего полями. В состав класса входит указатель на специальную таблицу, гдесодержится вся информация, нужная для вызова методов. От обычных процедур ифункций методы отличаются тем, что им при вызове передается указатель на тотобъект, который их вызвал. Поэтому обрабатываться будут поля именно тогообъекта, который вызвал метод. Внутри метода указатель на вызвавший его объектдоступен под зарезервированным именем self.
Понятие свойстваможно определить его как поле, доступное для чтения и записи не напрямую, ачерез соответствующие методы.
Классы могут бытьописаны либо в секции интерфейса модуля, либо на верхнем уровне вложенностисекции реализации. Не допускается описание классов внутри процедур и другихблоков кода.
Любой компонент (элемент управления) или объект в Delphi всегда является экземпляром класса.
Программно объект представляет собой переменную объектного типа.
Для каждого компонента Delphiсуществует свой класс, наследуемый от TComponent. Предком всех объектов,включая компоненты, является класс TObject.
Инкапсуляция — это создание защищенных объектов, доступ к свойствам иметодам которых разрешен только через определенные разработчиком . Иначе говоря, инкапсуляция — это предоставление разработчикуконкретного набора свойств и методов для управления поведением и свойствамиобъекта, определяемыми внутри класса.
Инкапсуляцияобеспечивает скрытие полей объекта с целью обеспечения доступа к ним толькопосредством методов класса.
В языке Delphiограничение доступа к полям объекта реализуется при помощи свойств объекта.Свойство объекта характеризуется полем, сохраняющим значение свойства, и двумяметодами, обеспечивающими доступ к полю свойства. Метод установки значениясвойства называется методом записи свойства (write), а метод получения значениясвойства — методом чтения свойства (read).
В описании классаперед именем свойства записывают слово property (свойство). Ключевое словоproperty обозначает свойство объекта, которое в отличие от обычных полей(переменных) класса имеет спецификаторы доступа обеспечивающие контроль доступак свойствам объекта.
После имени свойствауказывается его тип, затем — имена методов, обеспечивающих доступ к значениюсвойства. После слова read указывается имя метода, обеспечивающего чтениесвойства, после слова write — имя метода, отвечающего за запись свойства.
Пример описаниякласса TPerson, содержащего два свойства: Name и Address:
type
TName = string[15];TAddress = string[35];
TPerson =class // класс
private
FName:TName; // значение свойства Name
FAddress:TAddress; // значение свойства Address
ConstructorCreate(Name:Tname);
ProcedureShow;
Function GetName:TName;
Function GetAddress:TAddress;
ProcedureSetAddress(NewAddress:TAddress);
public
Property Name:Tname // свойство Name
readGetName; // доступно толькодля чтения
Property Address:TAddress // свойство Address
read GetAddress// доступно для чтения
write SetAddress;// и записи
end;
В программе дляустановки значения свойства записать обычную инструкцию присваивания значениясвойству. Например, чтобы присвоить значение свойству Address объекта student,достаточно записать
student.Address := ‘Гвардейский, ул.Зенитная1, кв.10’;
Внешне применениесвойств ничем не отличается от использования полей объекта. Однако междусвойством и полем объекта существует принципиальное отличие: при присвоении ичтении значения свойства автоматически вызывается процедура, которая выполняетнекоторую работу.
Наследование позволяет определять новые классы в терминах существующихклассов.
Новые классывозможно определять посредством добавления полей, свойств и методов к ужесуществующим классам. Такой механизм получения новых классов называетсяпорождением. При этом новый, порожденный класс (потомок) наследует свойства иметоды своего базового, родительского класса.
В объявлениикласса-потомка указывается класс родителя. Например, класс TEmployee(сотрудник) может быть порожден от рассмотренного выше класса TPerson путемдобавления поля FDepartment (отдел). Объявление класса TEmplioyee в этом случаеможет выглядеть так:
TEmployee = class(TPerson)
FDepartment:integer; // номер отдела
constructorCreate(Name:TName; Dep:integer);
end;
Заключенное в скобкиимя класса TPerson показывает, что класс TEmployee является производным откласса TPerson. В свою очередь, класс TPerson является базовым для классаTEmployee.
Класс TEmpioyeeдолжен иметь свой собственный конструктор, обеспечивающий инициализациюкласса-родителя и своих полей.
Пример реализацииконструктора класса TEmployee:
constructorTEmpioyee.Create(Name:Tname;Dep:integer);
begin
inheritedCreate(Name);
FDepartment:=Dep;
end;
В приведенномпримере директивой inherited вызывается конструктор родительского класса. Послеэтого присваивается значение полю класса-потомка.
После созданияобъекта производного класса в программе можно использовать поля и методыродительского класса. Ниже приведен фрагмент программы, демонстрирующий этувозможность.
engineer :=TEmployee.Create(‘Сидоров’,413);
engineer.address:= ‘ул.Блохина, д.8, кв.10’;
Первая инструкциясоздает объект типа TEmployee, вторая — устанавливает значение свойства,которое относится к родительскому классу.
Полиморфизм — это возможность различных объектов реагировать по-разному наодни и те же события, иначе говоря, возможность использовать одинаковые имена для методов,входящих в различные классы. Концепцияполиморфизма обеспечивает в случае применения метода к объекту использованиеименно того метода, который соответствует классу объекта. Синтаксис языка поддерживаетобщепринятую для объектно-ориентированного программирования нотацию: имя_объекта: свойство для ссылки на свойство объекта или имя_объекта: метод для вызова метода объекта. При этомимя_объекта может содержать как простую, так и квалифицированную ссылку. Квалифицированная ссылка содержит отделенные точкой именародительских объектов.
Пусть определены трикласса, один из которых является базовым для двух других:
tуре
// базовый класс TPerson= class
fname: string;// имя
constructorCreate(name:string);
functioninfo: string;
virtual;
end;
// производный от TPersonTStud = class(TPerson)
fgr:integer;// номер учебной труппы
constructorCreate(name:string;gr:integer);
function info: string;override; end;
// производный от TPersonTProf = class(TPerson)
fdep:string;// название кафедры
constructorCreate(name:string;dep:string);
functioninfo: string;
override;
end;
В каждом из этихклассов определен метод info. В базовом классе при помощи директивы virtualметод info объявлен виртуальным. Объявление метода виртуальным дает возможностьдочернему классу произвести замену виртуального метода своим собственным. Вкаждом дочернем классе определен свой метод info, который замещаетсоответствующий метод родительского класса (метод порожденного класса,замещающий виртуальный метод родительского класса, помечается директивойoverride).
Определение методаinfo для каждого класса:
function TPerson.info:string;
begin
result :=”;
end;
function TStud.info:string;
begin
result :=fname + ‘ гp.’ +IntTostr(fgr);
end;
function TProf.info:string;
begin
result :=fname + ‘ каф.’ + fdep;
end;
Так как оба классапорождены от одного и того же базового, объявить список студентов ипреподавателей можно так (следует помнить, что объект — это указатель):
list: array[l..SZL]of TPerson;
Объявить подобнымобразом список можно потому, что язык Delphi позволяет указателю народительский класс присвоить значение указателя на дочерний класс. Поэтомуэлементами массива list могут быть как объекты класса TStud, так и объектыкласса TProf.
Вывести списокстудентов и преподавателей можно применением метода info к элементам массива.Например, так:
st := ”;
for i:=l to SZL do //SZL — размер массива-списка
if list[i] о NIL
then st := st+ list[i].Info
+ #13; ShowMessage(st);
Во время работыпрограммы каждый элемент массива может содержать как объект типа xstud, так иобъект типа TProf. Концепция полиморфизма обеспечивает применение к объектуименно того метода, который соответствует типу объекта.
Перегрузка методов
Есть еще одна,совершенно особенная разновидность методов — перегружаемые.
Перегрузка методовнужна, чтобы произвести одинаковые или похожие действия с разнотипными данными.
Пример,иллюстрирующий статические методы:
type
TlstObj =class
FExtData: Extended;
procedureSetData(AValue: Extended);
end;
T2ndObj =class(TlstObj)
FIntData: Integer;
procedureSetData(AValue: Integer); end;
var T1:TlstObj;
T2:T2ndObj;
В этом случаепопытка вызова из объекта Т2 методов
Т2.SetData (1.0);
Т2.SetData(1);
вызовет ошибкукомпиляции на первой из двух строк. Для компилятора внутри Т2 статический методс параметром типа extended перекрыт, и он его «не признает».
Для выхода изсложившегося положения можно переименовать один из методов, например, создатьSetlntegerData и SetExtendedData, но если методов не два, а, например, сто,моментально возникнет путаница. Сделать методы виртуальными нельзя, посколькутип и количество параметров в одноименных виртуальных методах должны в точностисовпадать. Для разрешения этой ситуации существуют перегружаемые методы,объявляемые при помощи директивы overload:
type
TlstObj =class
FExtData: Extended;
procedureSetData(AValue: Extended);overload;
end;
T2ndObj =class(TlstObj)
FIntData: Integer;
procedureSetData(AValue: Integer); overload;
end;
Объявив методSetData перегружаемым, в программе можно использовать обе его реализацииодновременно. Это возможно потому, что компилятор определяет тип передаваемогопараметра (целый или с плавающей точкой) и в зависимости от этого подставитвызов соответствующего метода: для целочисленных данных — метод объектаT2ndobj, для данных с плавающей точкой — метод объекта Tistobj.
Можно перегрузить ивиртуальный (динамический) метод. Надо только в этом случае добавить директивуreintroduce:
type
TlstObj =class
FExtData: Extended;
procedureSetData(AValue: Extended); overload; virtual;
end;
T2ndObj =class(TlstObj)
FIntData: Integer;
procedureSetData(AValue: Integer); reintroduce; overload;
end;
На перегрузкуметодов накладывается ограничение — нельзя перегружать методы, находящиеся вобласти видимости published, т. е. те, которые будут использоваться вИнспекторе объектов.
Области видимости
В модели объектов языка Delphi существует механизм доступа к составным частямобъекта, определяющий области, где ими можно пользоваться (области видимости).Поля и методы могут относиться к четырем группам (секциям), отличающимсяобластями видимости. Методы и свойства могут быть общими (секция public),личными (секция private), защищенными (секция protected) иопубликованными (секция published). Есть еще и пятая группа, automated,она ранее использовалась для создания объектов СОМ; теперь она присутствует вязыке только для обратной совместимости с программами на Delphi версий 3—5.
Области видимости, определяемые первыми тремя директивами,таковы.
· Поля, свойства иметоды секции public не имеют ограничений на видимость. Они доступны издругих функций и методов объектов, как в данном модуле, так и во всех прочих,ссылающихся на него.
· Поля, свойства иметоды, находящиеся в секцииprivate, доступны только в методах класса ив функциях, содержащихся в том же модуле, что и описываемый класс. Такаядиректива позволяет полностью скрыть детали внутренней реализации класса.Свойства и методы из секции private можно изменять, и это не будетсказываться на программах, работающих с объектами этого класса. Единственныйспособ для кого-то другого обратиться к ним — переписать заново созданный вамимодуль (если, конечно, доступны исходные тексты).
· Поля, свойства иметоды секции protected также доступны только внутри модуля сописываемым классом. Но — и это главное — они доступны в классах, являющихсяпотомками данного класса, в том числе и в других модулях. Такие элементыособенно необходимы для разработчиков новых компонентов — потомков ужесуществующих. Оставляя свободу модернизации класса, они все же скрывают деталиреализации от того, кто только пользуется объектами этого класса.
СОЗДАНИЕ НОВОГО КЛАССА
Объявление типа
Для того чтобы создать новый класс, вinterface-секции кода модуля следует записать:
type
TNewClass =class(ParentClass)
end;
Каждая форма в проекте,разрабатываемом в Delphi, описывается отдельным модулем (создаваемымавтоматически при создании новой формы). Этот модуль описывает новый класс длякомпонента Form. Первоначально по умолчанию создается класс TForml, наследуемыйот класса TForm из VCL-библиотеки. Это автоматически записывается в модулеследующим образом:
type (Объявление класса}
TForml = class(TForm)
private
[Объявление private переменных иметодов}
public
{Объявление общедоступных переменныхи методов}
end;
var
Forml: TForml; {Создание экземпляракласса}
implementation
{Секция реализации методов)
end.
Объявление переменных и методовкласса
Переменные класса указываются после модификаторов доступа (public, private, protected, published, automated), определяющих их область видимости.Свойства, указанные после модификатора доступа published, являютсяобщедоступными и отображаются в инспекторе объектов.
После имени переменной или спискаимен, разделенных через запятую, указывается символ: и тип переменной. Типомможет быть как базовый тип Delphi (например. Integer, Boolean), так ипроизводный тип, в том числе реализуемый, как некоторый класс. Такой тип иногданазывается объектнымтипом.
При объявлении методов класса передименем метода указывается ключевое слово function или procedure. Для функцийтакже после имени функции через символ указывается тип возвращаемого значения.
Например:
type
TNewClass =class(ParentClass]
{Модификатор доступа public)
public
Varl: Integer;
Var2, Var3: TVarTypeClass;
procedure P1;
function F1: Integer;
end;
Объявление класса содержит толькообъявление переменных и методов. Реализация методов — функций и процедур — записывается в implementation-секции модуля.
Каждый модуль, создаваемый на основеразрабатываемой формы, представляет собой описание класса. Как правило,производного от класса TForm. Любой компонент, располагаемый в форме, такжеявляется экземпляром некоторого класса.
Классы в Delphi образуютиерархическое дерево. Будем называть классы из VCL-библиотеки Delphi базовыми классами. Иерархическое дерево для некоторогокласса любого компонента имеет корневым элементом класс TObject. Просмотретьиерархию классов-потомков можно в окне Exploring. Для того чтобы перейти внего, достаточно выполнить команду меню View|Browser или нажать клавиши Shift+CtrL+B.
 
/>
На рис.1 представлена страницаClasses окна ExploringClasses. На нейотображено иерархическое дерево наследования для класса TForm 1. В правой частиокна расположена панель, содержащая три страницы — Scope, Inheritance, References. Страница Scope содержит древовидную диаграмму всехобъектов, переменных и методов выделенного на левой панели класса. При этомветвь Inherited содержит имена класса-предка икласса-потомка. Страница Inheritance содержитподдерево иерархии классов, начиная с класса-предка для выделенного на левойпанели класса.
На страницеReferences можноузнать имена всех модулей и номера строк, в которых встречается имя данногокласса.
Для того чтобы добавить в проектсобственные описания производных классов, наиболее целесообразно создатьотдельный модуль и в interface-секции модуля записать все объявления классов.
Все классы VCL-библиотеки Delphiразбиты на группы, которые расположены в каталоге Delphi7\Source\VCL.Для того чтобы просмотреть файл библиотеки, достаточно выполнить File | Openи выбрать каталог и имя файла. Справа в окне кода программы (рис.2) будетпоказан код модуля, а слева — список всех объявленных в нем классов.
/>
 
СВОЙСТВА / МЕТОДЫ И ОБРАБОТЧИКИСОБЫТИЙ
Каждый объект обладает наборомсвойств. Свойства могут быть как наследуемые от родительского класса, так идобавленные индивидуально для создаваемого объекта. Список всех свойств объектаи их значений отображается в диалоговом окне Object Inspector.
Ссылка на свойство в программноммодуле записывается как
Имя_объекта.Свойство;
Метод — это процедура или функция,ассоциируемая с некоторым объектом.
Ссылка на методов программном модулезаписывается как
Имя_0бъекта. Метод;
Delphi-приложение выполняется в средеWindows, и как любое Windows-приложение, получает сообщения о возникающих длянего событиях. Управление приложением фактически сводится к обработкеполучаемых сообщений.
Методы, в которых содержится кодобработки события, называются обработчиками событий (Event Handler). Delphi автоматически генерирует процедуры обработкисобытий – обработчики событий для любого компонента. Приэтом имя обработчика событий формируется из имени компонента и названия события(например, EditlClick). Имя обработчика события автоматически квалифицируетсяименем класса формы.
Например: TForml.ButtonlClick(Sender:TObject);.
Для каждого компонента предусмотреноодно стандартноесобытие. Например, длякомандной кнопки, флажка, списка, поля ввода — это событие Click, а для формы — событие FormCreate.
Для того чтобы автоматически добавитьв модуль объявление и описание обработчика стандартного события, достаточновыполнить на компоненте формы или самой форме двойной щелчок мышью. Объявлениесобытия добавляется в interface-секцию модуля, а пустое описание события — вimplementation-секцию модуля. Далее в редакторе кода внутри уже имеющегосяблока begin end; следует только ввести код обработчика события.
Например:
procedureTForml.ButtonlClick(Sender: TObject);
begin
{место для введения кода}
end;
Для того чтобы добавить обработчиклюбого события, можно выбрать в инспекторе объектов страницуEvents ивыполнить двойной щелчок мышью в поле, расположенном справа от имени события.Это поле представляет собой комбинированное окно списка — в него можно вводитьновое значение имени обработчика события двойным щелчком мыши или выбирать имяуже существующей процедуры. Это позволяет при необходимости определять однупроцедуру обработки событий одновременно для нескольких событий.

2. ОПИСАНИЕ ПРЕДМЕТНОЙ ОБЛАСТИ (ПО)
 
2.1 Назначение программного продукта
Программа предназначена для решения заданных программнообыкновенных дифференциальных уравнений первого порядка методом Рунге – Кутта,вывода результата решения ОДУ на экран в виде графика в декартовой системекоординат.
2.2 Основные задачи
 
Программа обеспечивает решение следующих задач:
− ввод исходных данных;
− решение ОДУ и вывод результата решения в численном ианалитическом виде;
− обнуление результатов решения ОДУ;
− контроль корректности ввода исходных данных и выводна экран сообщение о содержании
ошибки с рекомендацией по её устранению;
− контроль возникновения в процессе вычислений ошибки«деление на ‘0’» и вывод на экран
соответствующего сообщения о содержании ошибки срекомендацией по её устранению.
2.3 Входные и выходные данные
Входными данными для программыявляются:
− начальное условие решения ОДУ− у'(х0) = у0.,
− начальное и конечное значения отрезка, в пределахкоторого находится решение ОДУ;
−величина шага дифференцирования,
−формула образцовой функции.
Выходными данными программы являются:
− массив (х1, у1; х2, у2;…; хi, уi)− решений выбранного дифференциального уравнения на заданном
интервале;
− график функции, которая,будучи подставленной, в исходное образцовое уравнение, обращает его в
тождество и одновременноудовлетворяет начальному условию.

3. ПРОЕКТИРОВАНИЕ
 
3.1 Выделение основных объектов ПО
 
− Объект класса TRKutta (Form1) – главная окно программы.
− Объект класса TRngeKutta (Form2) – окно вывода графика функции-решения ДУ.
− Объект класса TSpravka (Form3) – окно «О программе».
− Объект класса TRungeKutta – координатная плоскость и график функции;
3.2 Описание полейи методов
 
Класс TRKutta (родительский классTForm)
Поля класса:
x1 — значение x1(начало отрезка);
x2 — значение x2(конец отрезка);
yc — начальные значения (Y0) для передачи в графический модуль;
xc — начальные значения (х0)дляпередачи в графический модуль;
y — значение Y(x1);
h – зачение величины шага вычислений;
f — значение функции при начальныхусловиях
zx — массив значений аргумента;
zy — массив значений функции;
line_arr — размерность массивa;
Методы класса:
procedure Button1Click– вычисление значений функции – решения ОДУ;
procedure Button2Click– очистка полей ввода/вывода данных;
procedure Button3Click — вывод окна ГРАФИК;
procedure Button4Click — выход из программы;
procedure RadioGroup1Click — выбор образцовой функции;
procedure Button5Click — активация ввода образцовых функций;
procedure Button6Click — деактивация ввода образцовых функций;
procedure N7Click — выводинформации о программе;
Класс TRungeKutta(родительскийклассTObject)
Поля класса
x0,y0 — координатыначала координатных осей;
dx,dy — шаг координатной сетки (в пикселях)
y1,y2,xP,xL — засечки по оси Y и X
dlx,dly — шагметок (оцифровки) линий сетки по X и Y
cross — счетчик неоцифрованных линий сетки
dcross — количество неоцифрованных линий между оцифрованными
razm – размер массивов;
uzx — Динамический массив координат-X
uzy — Динамический массив координат-Y
uxc,uyc — Оцифровкапо осям
mx, my — масштабы по осям X и Y;
BaseMasht_X,BaseMasht_Y — МАХ значения элементов в массивах
Методы класса
function MaxAbsElementArray – определяет MAX элемент массива по модулю;
procedure UstanovkaParametrov – вычисляет исходные параметрынеобходимые для построения декартовой плоскости;
procedure KoordPloskost – вычерчивает координатнуюплоскость;
Конструктор
constructor TRungeKutta.CreateGr — создание объекта (график функции,координатная сетка, координатные оси)
Класс Form2 (родительский классTForm)
Поле класса (private)
RungeKutta — переменная-объект классаTRungeKutta;
Методы класса
procedure N4Click — выводграфика функции в окне ‘График’;
procedure N5Click — закрытиеокна ‘График’;
Класс Form3 (родительскийклассTForm)
Метод класса
procedure Button1Click– процедура вывода информации о программе
3.3 Иерархияклассов на основе выделенных объектов
 
/>

4. ОСНОВНЫЕ ФОРМЫ И КОМПОНЕНТЫ, ИСПОЛЬЗУЕМЫЕ ДЛЯ РЕАЛИЗАЦИИПРОГРАММЫ. ОСНОВНЫЕ АЛГОРИТМИЧЕСКИЕ РЕШЕНИЯ РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ
/>/>
/>

/>/>
/>
 
/>
/>/>

/>/>
/>/>

/>/>
/>
/> 

РУКОВОДСТВО
Теоретический материал
1. Решение дифференциальных уравнений
Пусть данодифференциальное уравнение первого порядка:
у’ = f(x)
и начальное условие его решения:
у'(х0) = у0..
Тогда решить уравнение — это значитнайти такую функцию у — φ(х), которая, будучи подставленной, в исходноеуравнение, обратит его в тождество и одновременно будет удовлетворено начальноеусловие. Задача отыскания функции у = φ (х) называется в математикезадачей Коши. При решении дифференциального уравнения порядка n задача Коши формулируется следующим образом.
Дано дифференциальное уравнениепорядка n:
у(n) = f(x, y, у’’,…,yn-1)
Необходимо найти такую функцию у = φ(х), которая, будучи подставленной в исходное уравнение, обратит его втождество и одновременно будут удовлетворены следующие п начальных условий:
у(х0) = у0
у'(х0) = у’0
… .
уn-1(х0) = уn-10

4.1 Метод Рунге-Кутта
 
Метод Рунге-Кутта обладает болеевысокой точностью, чем методы Эйлера за счет снижения методических ошибок. Идеяметода состоит в следующем.
По методу Эйлера решениедифференциального уравнения первого порядка определяется из соотношения:
yi+1 = yi + Δyi;
где Δyi= hf (хi,yi) = hу’ (хi, yi).
Тогда приращениеΔyi, может быть найдено путеминтегрирования:
/>
Или окончательно
/>
Вычислим теперь интеграл по методупрямоугольников:
yi+1 = yi +(xi+1 — xi)f(xi, yi) = yi+ hf(xi, yi).
Из полученного выражения видно, чтовычисление интеграла по методу прямоугольников приводит к формуле Эйлера.
Вычислим интеграл по формулетрапеций:

yi+1 = yi +0,5h(f(xi,yi)+ f(xi+1, yi+1))
Из выражения видно, что оно совпадаетс расчетной формулой усовершенствованного метода Эйлера-Коши. Для полученияболее точного решения дифференциального уравнения следует воспользоваться болееточными методами вычисления интеграла. В методе Рунге-Кутта искомый интегралпредставляется в виде следующей конечной суммы:
/>
где Pi — некоторые числа, зависящие от q; Ki(h) — функции, зависящие от вида подынтегральной функции f(x,y) и шага интегрирования h, вычисляемые по следующим формулам:
K1(h) = hf(x,y);
K2(h) = hf(x +a2h, y + β21K1(h));
K3(h) = hf(x +a3h, y + β31K1(h) + β 32K2(h));
Kn(h) = hf(x +aqh,, y + βq1K1(h) +… + βq,q-1Kq-1(h)).
Значения p, α, β получают из соображений высокой точностивычислений. Формулы Рунге-Кутта третьего порядка (q= 3)имеют следующий вид:
/>
K1=hf(xi, yi);
K2=hf(xi +0,5h, yi+0,5 K1);
K3=hf(xi+h,yi+K1+2K2).

Наиболее часто используется методРунге-Кутта четвертого порядка, для которого расчетные формулы имеют следующийвид:
/>
K1=hf(xi, yi);
K2=hf(xi +0,5h, yi+0,5 K1);
K3=hf(xi+0,5h,yi+0,5K2).
K3=hf(xi+h,yi+K3).
Формулы Рунге-Кутта имеют погрешности порядка h q+1. Погрешность метода Рунге-Кутта четвертого порядкаимеет порядок h5
 
4.2 Описание программы ” РЕШЕНИЕ ОДУ “
 
Программа ”Решение ОДУ“ достаточно проста в использовании.
При запуске программы открывается главное окно программы (рис.4), с установленными по умолчанию начальными условиями в полях ввода.
Назначение элементов ввода данных.
1. Поля X1, X2, Y(x1), Hпредназначены для ввода начального и конечногозначений отрезка, на котором ищется решение дифференциального уравнения,значения функции при аргументе равномХ1 и величины шагадифференцирования;
2. В поле dY выводится формула дифференциальногоуравнения 1-й степени, выбранная для решения;
3. В поле dY(x1,y1) выводится значение производной в исходной точке.

/>
Рис.4
Назначение элементов управления и контроля.
1. При нажатиикнопки EXAMPLE активируются “радиокнопки” выборауравнений;
2. Щелчком “радиокнопки”выбирается соответствующее ей уравнение, вид формулы контролируется по еёотображению в поле dY;
3. Щелчком покнопке ВЫЧИСЛИТЬ находятся приближенные решения выбранногодифференциального уравнения на заданном интервале;
4. Решениядифференциального уравнения в виде пар значений X— Y выводятся в поля X и Y; (рис. 5.)
По окончании вычислений активируются кнопка ГРАФИК ипункт меню ГРАФИК главного окна системы.

/>
Рис.5
 
4.3 Назначение элементов графического окна программы
 
Вход в графическое окно осуществляется с помощью кнопок ГРАФИКнаглавной формеили пункт меню ГРАФИК (рис. 6).
С помощью кнопки ВЫЧЕРТИТЬ на координатную плоскостьвыводится график функции – решение дифференциального уравнения на заданноминтервале.

/>
рис.6
 
4.4 Реакция программы привозникновении ошибок
 
При вводе пользователем ошибочныхданных (отсутствии начальных условий, некорректных значений переменных)программа выдает сообщение об ошибке (рис.7 а, б) рис.7а.рис.7б.
/>/>
рис 7а                                         Рис.7б
 

Версия DELPHI
/>
 
4.5 Перечень компонент DELPHIиспользованных в программе
 
В Form1 использованыкомпоненты:
— Edit1.text, Edit2.text, Edit3.text, Edit4.text – для ввода начальных условийдифференциального
уравнения
— Memo4.TMemo – для вывода формулы уравнения;
— Memo1.TMemo, Memo2.TMemo- для вывода результатов вычислений;
— Memo3.TMemo – для вывода значения производной вточке (Х0,Y0)
— ScrollBars ssVertical в свойствах Memo1.TMemo,Memo2.TMemo;
— Button1 “Вычислить”, Button2 “Очистить”, Button3 “График”, Button4 “Выход”,
Button5 “Example”, Button6“UnExample”;
— Label1.TLabel — Label9.TLabel – для отображения назначения компонентов Memo и Edit;
— RadioGroup – длявыбора вида уравнения;
— MainMenu ;
В Form2 использованыкомпоненты:
— MainMenu- для построенияграфика;
В Form3 использованыкомпоненты:
— Panel1.T Panel – для размещения информации о программе;
— Label1.TLabel – Label14.TLabel– для отображения информации о программе;
— Button1.T Button “OK” –для выхода из окна
 

5. ТЕХНИЧЕСКИЕ ХАРАКТЕРИСТИКИ И ТРЕБОВАНИЯ К ПО
 
Технические характеристики
Программа работает в среде операционных систем Windows 9х, NT.
Требования к ПО
Минимальные системные требования
a процессор Intel486 с рабочей частотой 66 MHz ивыше;
b) операционная система Windows 95, 98, NT 4.0, 2000, XP;
с) 16 Мбайт оперативной памяти (или более);
d) 3 Мбайт свободного пространства на жёстком диске.

6. ТЕКСТ ПРОГРАММЫ
 
Код программы
unitRKt;
interface
uses
Windows, Messages, SysUtils, Classes,Graphics, Controls, Forms, Dialogs,
StdCtrls, CheckLst, ComCtrls,ExtCtrls,math, Menus;
type
TRKutta = class(TForm)
Label2: TLabel;
Label3: TLabel;
Label5: TLabel;
Label6: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Memo1: TMemo;
Memo2: TMemo;
Button1: TButton;
Button2: TButton;
Label4: TLabel;
Label7: TLabel;
Button3: TButton;
Button4: TButton;
Label9: TLabel;
RadioGroup1: TRadioGroup;
Button5: TButton;
Memo3: TMemo;
Button6: TButton;
MainMenu1: TMainMenu;
N1: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
Example1: TMenuItem;
UnExample1: TMenuItem;
N5: TMenuItem;
N7: TMenuItem;
N2: TMenuItem;
N9: TMenuItem;
N8: TMenuItem;
Label1: TLabel;
Memo4: TMemo;
Label8: TLabel;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
procedure Button1Click(Sender:TObject);
procedure Button2Click(Sender:TObject);
procedure Button3Click(Sender:TObject);
procedure Button4Click(Sender:TObject);
procedure RadioGroup1Click(Sender:TObject);
procedure Button5Click(Sender:TObject);
procedure Button6Click(Sender:TObject);
procedure N7Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
RKutta: TRKutta;
x1,x2,yc,xc,y,h:extended;
line_arr:integer; // размерность массивa
f:real; // значениефункции при начальных условиях
zx:array of real;
zy:array of real;
implementation
uses RungeKutta, Spravka;
{$R *.DFM}
procedureTRKutta.Button1Click(Sender: TObject);
var k1,k2,k3,k4:extended;
t:integer;
begin
Memo1.Clear;
Memo2.Clear;
memo1.Enabled:=true;
memo2.Enabled:=true;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=False;
//Проверка возможности ввода начальных условий иинициализация переменных
try
// инструкции, которые могут вызвать исключение (ошибку)
x1:=StrToFloat(Edit1.Text); //инициализация(ввод) x1(начало отрезка)
xc:=StrToFloat(Edit1.Text); //передача начальных условий (х0)в графическиймодуль
x2:=StrToFloat(Edit2.Text); //инициализация(ввод) x2(конец отрезка)
y:=StrToFloat(Edit3.Text); //инициализация(ввод) Y(x1)
yc:=StrToFloat(Edit3.Text); //передача начальных условий (Y0)в графический модуль
h:=StrToFloat(Edit4.Text); //инициализация(ввод) H -величины шага вычислений
//определение размера массивов содержащего значения аргументаи функции
line_arr:=round(abs((x2-x1)/h))+1;
//Установка размера динамических массивов zx, zy
SetLength(zx, line_arr);
SetLength(zy, line_arr);
t:=0; // счётчик
while x1
do
begin
zx[t]:=x1;
zy[t]:=y;
k1:=h*f;
if (y+(k1/2))=0 then beginshowmessage (‘Деление на 0!’+#13+’ Измените h’); break;
end;
k2:=h*((y+(k1/2))-(2*(x1+(h/2)))/(y+(k1/2)));
if (y+(k2/2))=0 then beginshowmessage (‘Деление на 0!’+#13+’ Измените h’); break;
end;
k3:=h*((y+(k2/2))-(2*(x1+(h/2)))/(y+(k2/2)));
if (y+k3)=0 then begin showmessage(‘Деление на 0!’+#13+’ Измените h’);break;
end;
k4:=h*(y+k3-2*(x1+(h/2)))/(y+k3);
x1:=x1+h;
y:=y+(1/6)*(k1+2*k2+2*k3+k4);
t:=t+1;
Memo1.Lines.Add(‘x[‘+floattostr(t)+’]=’+floattostr(x1));
Memo2.Lines.Add(‘y[‘+floattostr(t)+’]=’+floattostr(y));
end;
except
on EConvertError do // невозможно преобразовать строку символов в число
begin
MessageDlg(‘Некорректные значения переменных’,mtError,[mbOk],0);
exit;
end;
end;
{ | Подключение кнопок: |
| — Button3- ‘ГРАФИК’: входа в графический модуль |
| — нопки N3 — ‘EXAMPLE’: образцовых функций | }
if ((y+(k1/2))=0) or ((y+(k2/2))=0)or((y+k3)=0) then
begin
Button3.Enabled:=False;
N3.Enabled:=False;
end
else
begin
Button3.Enabled:=True;
N3.Enabled:=True;
end;end;
//——————————————————————————
procedureTRKutta.Button2Click(Sender: TObject);
begin
memo1.Clear;
MEMO2.Clear;
MEMO3.Clear;
memo4.Clear;
edit1.Clear;
edit2.Clear;
edit3.Clear;
edit4.Clear;
end;
//——————————————————————————
{Процедура вывода окна ГРАФИК}
procedureTRKutta.Button3Click(Sender: TObject);
begin
Button3.enabled:=false;
N3.Enabled:=false;
Form2.ShowModal;
end;
//——————————————————————————
{Процедура выхода из программы}
procedureTRKutta.Button4Click(Sender: TObject);
begin
Close;
end;
//——————————————————————————
{Процедура выбора образцовой функции}
procedureTRKutta.RadioGroup1Click(Sender: TObject);
var x_rg,y_rg:extended;
begin
try
y_rg:=strtofloat(edit3.Text); //вводY(x1)
x_rg:=strtofloat(edit1.Text); //вводX1
{——————————————————————————}
if RadioGroup1.ItemIndex=0 then
begin
if x_rg=0 then
begin
ShowMessage(‘введите X1 неравное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo3.clear;
Memo4.Clear;
Memo4.Lines.Add(‘ -(y+1)/x ‘); выводформулы функции в окно «dY»
f:=-(y_rg+1)/x_rg; //вычислениезначения dY
Memo3.lines.Add(”+floattostr(f)); //вывод значения dY в окно «dY(x1,y1)»
// сброс радиокнопки (с целью корретного вычисления
// значения dy(x1,y1) при вводе других данных)
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=1 then
begin
if y_rg=0 then
begin
ShowMessage(‘введите Y(x1) неравное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘x*(x^2-1)/(x^2+1)*y’);
f:=x_rg*(power(x_rg,2)-1)/(power(x_rg,2)+1)*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=2 then
begin
if x_rg=0 then
begin
ShowMessage(‘введите X1 неравное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo3.Clear;
Memo4.Clear;
Memo4.Lines.Add(‘(x*cos(y/x))^2+y)/x’);
f:=x_rg*(POWER(cos(y_rg/x_rg),2)+y_rg)/x_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=3 then
begin
if x_rg=0 then
begin
ShowMessage(‘введите X1 неравное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo3.Clear;
Memo4.Clear;
Memo4.Lines.Add(‘2*x*sin(x)+y*ctg(x)’);
f:=2*x_rg*sin(x_rg)+y_rg*cot(x_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=4 then
begin
Memo3.Clear;
Memo4.Clear;
Memo4.Lines.Add(‘((e^y)+cos(x) ‘);
f:=(exp(y_rg))+cos(x_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=5 then
begin
Memo3.Clear;
Memo4.Clear;
Memo4.Lines.Add(‘e^(x+y) ‘);
f:=exp(y_rg+x_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=6 then
begin
if ((x_rg=0))or((x_rg>=0) and (y_rg
begin
ShowMessage(‘X1 / Y(X1) не должны быть
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘(y/x)ln(y/x) ‘);
f:=(y_rg/x_rg)*ln(y_rg/x_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=7 then
begin
if x_rg=0 then
begin
ShowMessage(‘введите X1 неравное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘ sin(y/x)+y/x ‘);
f:=sin(y_rg/x_rg)+y_rg/x_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=8 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ 6x-sin(x) ‘);
f:=6*x_rg-sin(x_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=9 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ x+2y ‘);
f:=x_rg+2*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=10 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ e^x-y ‘);
f:=exp(x_rg)-y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=11 then
begin
if x_rg=0 then
begin
ShowMessage(‘введите X1 не равное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘ y*ctg(x) ‘);
f:=cot(x_rg)*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=12 then
begin
if x_rg=0 then
begin
ShowMessage(‘введите X1 не равное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘(e^x-y)/x ‘);
f:=(exp(x_rg)-y_rg)/x_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=13 then
begin
if x_rg*y_rg
begin
ShowMessage(‘введите X1*Y(X1) >=0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘(x*y)^(1/2) ‘);
f:=power(x_rg*y_rg,1/2);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=14 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ x+y ‘);
f:=x_rg+y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=15 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ x*y ‘);
f:=x_rg*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=16 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘e^(x*y) ‘);
f:=exp(x_rg*y_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=17 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘(e^x*y) ‘);
f:=exp(x_rg)*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=18 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘(x^2)*y ‘);
f:=power(x_rg,2)*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=19 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘-2*x+(2+x+x^2)*y^2’);
f:=-2*x_rg+(2+x_rg+power(x_rg,2))*power(y_rg,2);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=20 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘-x*y+(x+1)*y^2 ‘);
f:=-x_rg*y_rg+(x_rg+1)*power(y_rg,3);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=21 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ x^2*y^2 ‘);
f:=power(x_rg,2)*power(y_rg,2);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=22 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘ e^(x-y) ‘);
f:=exp(x_rg-y_rg);
Memo3.clear;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=23 then
begin
if (x_rg=-y_rg) then
begin
ShowMessage(‘введите Y(x1)неравноеX1’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘(x-(y/2))/(x+y) ‘);
f:=(x_rg-0.5*y_rg)/(x_rg+y_rg);
Memo3.clear;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=24 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘(x+1)*(y+1) ‘);
f:=(x_rg+1)*(y_rg+1);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=25 then
begin
Memo4.Clear;
Memo4.Lines.Add(‘x*e^(y) ‘);
f:=x_rg*exp(y_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=26 then
begin
if (2*x_rg=-y_rg) then
begin
ShowMessage(‘введите Y(x1) неравное-2*X1’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘(x+1)/(2*x+y) ‘);
f:=(x_rg+1)/(2*x_rg+y_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=27 then
begin
if (x_rg=0)or(y_rg=0) then
begin
ShowMessage(‘введите Y(x1) неравное0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘((x+1)*(y^2))/x*y’);
f:=((x_rg+1)*power(y_rg,2))/x_rg*y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=28 then
begin
if (x_rg=-y_rg) then
begin
ShowMessage(‘введите Y(x1) неравное-X1’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘(3.4-x*y)/(x+y) ‘);
f:=(3.4-x_rg*y_rg)/(x_rg+y_rg);
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=29 then
begin
if y_rg=0 then
begin
ShowMessage(‘введите Y(x1) не равное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘y-2x/y ‘);
f:=y_rg-2*x_rg/y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end;
{——————————————————————————}
if RadioGroup1.ItemIndex=30 then
begin
if y_rg=0 then
begin
ShowMessage(‘введите Y(x1) не равное 0’);
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end
else
begin
Memo4.Clear;
Memo4.Lines.Add(‘ x/y ‘);
f:=x_rg/y_rg;
Memo3.lines.Add(”+floattostr(f));
Button1.Enabled:=True;
RadioGroup1.Enabled:=False;
RadioGroup1.ItemIndex:=31;
end;
end
{——————————————————————————}
except
on EConvertError do // невозможно преобразовать строку символов в число
begin
MessageDlg(‘Некорректные значения переменных’,mtError,[mbOk],0);
exit;
end;
end;
end;
//——————————————————————————
{Активация ввода образцовых функций}
procedureTRKutta.Button5Click(Sender: TObject);
begin
memo4.clear;
memo3.clear;
RadioGroup1.Enabled:=True; memo1.clear;memo2.Clear;memo3.clear;
memo3.lines.Add(”+floattostr(f));
end;
//——————————————————————————
{Деактивация ввода образцовых функций}
procedure TRKutta.Button6Click(Sender: TObject);
begin
RadioGroup1.Enabled:=False;
Memo3.lines.Add(”+floattostr(f));
end;
//——————————————————————————
{Вывод информации о программе}
procedure TRKutta.N7Click(Sender:TObject);
begin
Form3.ShowModal;
end;
//——————————————————————————
end.
{====================================================}
unit RngeKutta;
interface
uses
Windows, Messages, SysUtils,Variants, Classes, Graphics, Controls, Forms,
Dialogs,StdCtrls,Rkt,Menus;
type
TRungeKutta=class(TObject)
constructor CreateGr(var hzx:array ofreal;var hzy:array of real;var lin_arr:integer);
private
{ Private declarations }
public
{ Public declarations }
x0,y0:integer; //координаты начала координатныхосей, 2*x0,2*y0 — высота
// и ширина области вывода координатной сетки
dx,dy:integer; // шаг координатной сетки (впикселях)
y1,y2,xP,xL:integer;// засечкипо оси Y и X
dlx,dly:real; // шаг меток (оцифровки) линийсетки по X и Y
cross:integer;// счетчик неоцифрованных линий сетки
dcross:integer;// количество неоцифрованных линий между оцифрованными
BaseMasht_X,BaseMasht_Y:extended; //МАХ значения элементов в массивах
razm:integer;
uzx:array of real; //Динамический массив координат-X
uzy:array of real; //Динамический массив координат-Y
uxc,uyc:extended; // Оцифровка по осям
mx,my:extended;
function MaxAbsElementArray(arr:arrayof real;razmer:integer):real;
procedure UstanovkaParametrov();
procedure KoordPloskost;
end;
TForm2 = class(TForm)
MainMenu1: TMainMenu;
N4: TMenuItem;
N5: TMenuItem;
procedure N4Click(Sender: TObject);
procedure N5Click(Sender: TObject);
private
{ Private declarations }
RungeKutta:TRungeKutta; //Объявление переменной — объектакласса
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
functionTRungeKutta.MaxAbsElementArray(arr:array of real;razmer:integer):real;
var i:integer;
max:real;
begin
i:=1;
max:=arr[1];
while irazmer do
begin
i:=i+1;
if abs(arr[i])>max then
begin
max:=abs(arr[i]);
end;
end;
MaxAbsElementArray:=max;
end;
//——————————————————————————
procedureTRungeKutta.UstanovkaParametrov();
begin
//определение maxабсолютного значения функции (ордината)
BaseMasht_Y:=MaxAbsElementArray(uzy,razm)+1;
//определение maxабсолютного значения аргумента функции (абсцисса)
BaseMasht_X:=MaxAbsElementArray(uzx,razm);
y0:=round(Form2.ClientHeight/2); //оси начинаются в точке (X0,Y0)
x0:=round(Form2.ClientWidth/2);
dcross:=1; // помечать линии сетки X: 1 — каждую;
// 2 — через одну;
// 3 — через две;
dlx:=round(BaseMasht_X)/10; // вес меток оси X
dly:=round(BaseMasht_Y)/10; // весметок оси Y ,
dx:=round(x0/10); // шаг координатной сетки впикселях
dy:=round(y0/10); // шаг координатной сетки впикселях
mx:=round(x0/round(BaseMasht_X)+1);//вычисление масштаба по оси X
my:=round(y0/round(BaseMasht_Y)+1);//вычислениемасштаба по оси Y
end;
//——————————————————————————
procedure TRungeKutta.KoordPloskost;
begin
uxc:=0;
uyc:=0;
with form2.Canvas do
begin
cross:=dcross;
//——————————————————————————
//Нанесение засечек и оцифровка координатных осей I,II квадрантов
// засечки и оцифровка по оси X
xP:=x0;
xL:=x0;
repeat
MoveTo(xP,y0-2);LineTo(xP,y0+2); //засечка
MoveTo(xL,y0-2);LineTo(xL,y0+2); //засечка
cross:=cross-1;
if cross = 0 then //оцифровка
begin
TextOut(xP-8,y0+3,FloatToStr(uxc));
TextOut(xL-8,y0+3,FloatToStr(-uxc));
cross:=dcross;
uxc:=uxc+dlx;
end;
Pen.Style:=psDot;
MoveTo(xP,2*y0);LineTo(xP,-2*y0); //линия сетки
MoveTo(xL,2*y0);LineTo(xL,-2*y0);
Pen.Style:=psSolid;
xP:=xP+dx;
xL:=xL-dx;
until (xP>2*x0);
//——————————————————————————
//Нанесение засечек и оцифровка координатных осей III, IV квадрантов
// засечки, и оцифровка по оси Y
y1:=y0-dy;
y2:=y0+dy;
repeat
MoveTo(x0-2,y1);LineTo(x0+2,y1); //засечка
MoveTo(x0-2,y2);LineTo(x0+2,y2);
uyc:=uyc+dly;
TextOut(x0-20,y1,FloatToStr(uyc)); //оцифровка
TextOut(x0-20,y2,FloatToStr(-uyc));
Pen.Style:=psDot;
MoveTo(10,y1);LineTo(2*x0-10,y1); //линия сетки
MoveTo(10,y2);LineTo(2*x0-10,y2);
Pen.Style:=psSolid;
y2:=y2+dy;
y1:=y1-dy;
until (y2>2*y0);
//——————————————————————————
MoveTo(x0,2*y0); LineTo(x0,0); // осьY
MoveTo(0,y0); LineTo(2*x0,y0); // осьX
end;
end;
//—————————————————————————–
//создание объекта (график функции, координатная сетка,координатные оси)
constructor TRungeKutta.CreateGr(varhzx:array of real;var hzy:array of real;var lin_arr:integer);
var n:integer;
begin
SetLength(uzx,lin_arr); //Установкаразмера массива uzx
SetLength(uzy,lin_arr); //Установка размера массива uzy
razm:= lin_arr;
for n:=0 to lin_arr do
begin
uzx[n]:=hzx[n]; //инициализация массива uzx
uzy[n]:=hzy[n]; //инициализация массива uzy
end;
UstanovkaParametrov;
KoordPloskost;
for n:=0 to (lin_arr-1) do
begin
form2.canvas.Pixels[(x0+ROUND(uzx[n]*mx)),(y0-round((uzy[n]*my)))]:=clRed;
end;
end;
//——————————————————————————
{Процедура N4Click выводит график функции вустановленном масштабе в окне ‘График’ }
procedure TForm2.N4Click(Sender:TObject);
begin
form2.Canvas.FillRect(Rect(0,0,ClientWidth,ClientHeight));
TRungeKutta.CreateGr(zx,zy,line_arr);
end;
//——————————————————————————
{Процедура N5Click закрывает окно вывода графикафункции — результата решния ДУ }
procedure TForm2.N5Click(Sender:TObject);
begin
close;
end;
end.
{====================================================}
Unit Spravka;
interface
uses
Windows, Messages, SysUtils,Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm3 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Button1: TButton;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Label6: TLabel;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
Label14: TLabel;
procedure Button1Click(Sender:TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
//——————————————————————————
{Ввыводинформации о программе}
procedure TForm3.Button1Click(Sender:TObject);
begin
Caption := ‘OK’;
ModalResult := mrOK;
OnClick := Button1Click;
end;
end.
{===============================================}

7. РЕШЕНИЕ ДИФФЕРЕНЦИАЛЬНОГО УРАВНЕНИЯ Y= Y−2X/YМЕТОДОМ РУНГЕ – КУТТА В СРЕДЕ EXCEL
дифференциальноеуравнение программирование
/>
/>
2. Решениедифференциального уравнения Y= Y−2X/Yпрограммой «РЕШЕНИЕ ОДУ» показано на рис. 5 ирис. 6.(стр. 22 — 23 )
 

ВЫВОД
 
Программа «Решение ОДУ» решает заданные дифференциальныеуравнения первой степени с достаточно высокой степенью точности.