|
||||||||||||||||||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Вычисление первой и второй производнойЦель работы. Развить навыки объектно-ориентированного программирования, использовав для реализации задачи про интерпретатор механизмы инкапсуляции, наследования, полиморфизма, динамического связывания и виртуальных функций. Усовершенствовать интерпретатор математических выражений (см. лаб.7) с целью нахождения значения выражения и его производных произвольного порядка. Применить интерпретатор для решения задачи о полете ракеты. Вычислить путь, скорость и ускорения ракеты, движение которой описывается математическим выражением, которые вводят в компьютер во время работы программы. В выражениях ограничиться операциями добавления, вычитания, умножения и деления, которые будут применяться к действительным числам и переменным. Анализ задачи. Задачу будем решать по схеме, аналогичной к описанной в лаб. 7. Для этого создадим набор классов, связанных между собою такими отношениями наследственности: Telement
Real Var Plus Minus Mult Div
Рис.1. Иерархическое дерево
где класс Real реализует число, Var - переменную, Plus, Minus, Mult, Div -арифметические операции „+”, „-“, „*”, „/” соответственно. К описанию базового класса Telement из лаб.7 прибавим три виртуальные функции copy(), differ() и set_var(): class Telement { protected: Telement *left, *right; Telement (Telement* L,Telement* R) { left = L; right = R; } public: ~Telement(void) { delete left; delete right;} virtual void set_var(double X) { if (left) left -> set_var(X); if (right) right -> set_var(X); } }; Функция set_var() предоставляет переменной xконкретное значение. В производном классе Var (переменная) эта функция будет переопределена. Во всех других классах set_var() не переопределяется, поэтому C++ осуществит вызов этой функции из базового класса, который приведет к рекурсивным вызовам ее вниз по дереву. Функция differ() в производных классах должна возвращать указатель на новое дерево, которое определено дифференцированием поддерева, подвешенного к вершине вызова этой функции. Функция copy() создает в памяти копию дерева и возвращает указатель на его вершину. Эта функция есть вспомогательной и используется для реализации differ() в производных классах. Рассмотрим реализацию класса Real: class Real: public Telement{ double f; public: Real(double F):Telement(NULL,NULL){f=F;} double rezult(void) { return f; } Telement* copy (void) { return new Real(f);} Telement* differ(void) { return new Real(0);} }
Функция copy() делает копию объекта и возвращает указатель на эту копию. Функция differ() возвращает указатель на созданный объект класса Real со значением нуля для поля f, поскольку производной любого действительного числа есть число 0. Аналогично реализуется класс Var: class Var: public Telement { double x; public: Var(double X = O):Telement(NULL, NULL) {x = X;) double rezult(void) { return x;} Telement* copy(void) { return new Var(x);} Telement* differ(void) { return new Real(1.0);} void set_var(double X) {x = X;} Реализация этого класса подобна предыдущему. Функция Var::set_var() переопределяет виртуальную функцию из базового класса. Этот механизм определения переменной есть довольно удобным: вызовется функция set_var() с аргументом - значением переменной для вершины дерева, и по целому дереву все вершины типа Number будут наполнены этим значением (см. описание Var::set_var()). Вершины других типов лишь будут передавать вызов set_var() вниз по подчиненным ребрам (см. описание Tele-ment::set_var()). По умолчанию переменная инициализуется нулем, что видно из заголовка конструктора Var::Var(). Опишем класс Plus: struct Plus:public Telement { Plus(Telement* L,Telement* R):Telement(L, R) {}; double rezult(void) { return left -> rezult() + right -> rezult(); Telement* copy(void) { return new Plus(left -> copy(), right -> copy()); Telement* differ(void) { return new Plus(left -> differ(), right -> differ()); } В функции Plus::differ() использовано правило дифференцирования суммы: (u + v)’ = u' + v'. Итак, дифференцирование дерева + +
U V дает дерево: U’ V’
Аналогично создадим классы других арифметических операций: struct Minus:public Telement { Minus(Telement* L,Telement* R):Telement(L, R) doublerezult(void) { return left->rezult() - right->rezult(); Telement* copy(void) { return new Minus(left->copy(), right->copy()); Telement* differ(void) { return new Minus(left->differ(), right->differ()); } }; struct Mult:public Telement { Mult(Telement* L, Telement* R):Telement(L, R) {}; double rezult(void) {return left->rezult()*right->rezult();} Telement* copy(void) {return new Mult(left->copy(),right->copy());} Telement* differ(void) { return new Plus(new Mult(left->differ(), right->copy()), new Mult(left->copy(), right->differ())); } //—:------------------------------ — struct Div:public Telement { Div(Telement* L,Telement* R):Telement(L, R) {}; double rezult(void) {return left->rezult() / right->rezult();} Telement* copy(void) {return new Div(left->copy(), right->copy());} Telement* differ(void) {return new Div(new Minus(new Mult(left->differ(), right->copy()), new Mult(left->copy(), right->differ())), new Mult(right->copy(), right->copy())); } }; Теперь рассмотрим функцию form(), которая по заданным математическим выражением строит дерево объектов.
//Декларация вспомогательной функции int PosFromEnd(AnsiString s, AnsiString sub); Telement* form(AnsiString s) { Telement* h; int и, p, I = s.Length(); AnsiString s1, s2; // Анализируем справа налево: if ((p = PosFromEnd(s,"+")) > 1) // Если направляется на “+” { s1 = s.SubString(1, p - 1); s2 = s.SubString(p + 1,1 - p); h = new Plus(form(s1), form(s2)); //Создаем вершину Plus } else if ((p = PosFromEnd(s,"-")) > 1) // Если направляется на “-” { s1 =s.SubString(1, p-1); s2 = s.SubString(p + 1,1 - p); h = new Minus(form(s1), form(s2)); //Создаем вершину Minus } else if ((p = PosFromEnd(s, "*")) > 1) // Если наталкиваемся на ”*” { s1 =s.SubString(1, p-1); s2 = s.SubString(p + 1,1 - p); h = new Mult(form(s1), form(s2)); //Создаем вершину Mult } else if ((p = PosFromEnd(s, “/ ”)) > 1)// Если наталкиваемся на “/ ” {
s1 =s.SubString(1, p-1); s2 = s.SubString(p + 1,1 - p); h = new Div(form(s1), form(s2)); // Создаем вершину Div } else if (s == "x") h = new Var(); // Создаем вершину Var Else h = new Real(StrToFloat(s)); // Создаем Real return h; } Эта функция аналогичная к приведенной в лаб.7 за исключением направления поиска операнда, ведь операции "-" и "/" не владеют свойством аддитивности. Строка с математическим выражением будем анализировать справа налево, поскольку арифметические операции одного порядка выполняются слева направо. В самом деле, поскольку корень дерева отвечает за последнюю операцию, которая будет выполняться, этот оператор в выражении будет размещен правее от других того же порядка. Опишем функцию, которая находит позицию из конца первой подстроки в этой строке:
lnt PosFromEnd(AnsiString s, AnsiString sub) } int I = s.Length(); AnsiString p; p.SetLength(l); for(int i = 1; i <= I; i++) p[l - i + 1] = s[i]; // Оборачиваем строку if (p.Pos(sub) > 0) return I - p.Pos(sub) + 1; else return 0; }
Выводы. Приобретенные навыки можно использовать для решения таких задач: • аналитическое исследование математических выражений; • нахождения значений функции для задачи табулирования • построение графика функции, заданной аналитически, и ее производных произвольного порядка; • задание входных данных (математических функций) для
Ход работы 1. Загрузите среду визуального программирования C++ Builder. 2. Создайте форму, показанную на рис. 1. Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.016 сек.) |