АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Вычисление первой и второй производной

Читайте также:
  1. E) первой половине 1920-х гг.
  2. I. Первый (и главным) принцип оказания первой помощи при ранениях является остановка кровотечения любым доступным на данный момент способом.
  3. I. Первым (и главным) принципом оказания первой помощи при ранениях верхней конечности является остановка кровотечения любым доступным на данный момент способом.
  4. I. Поэтому первым (и главным) принципом оказания первой помощи при ранениях является остановка кровотечения любым доступным на данный момент способом.
  5. I.4.3.Изменение государственного управления на основе новой Конституции СССР в предверии второй мировой войны
  6. I.5.1.Изменение государственного управления под влиянием начавшейся в 1939 г. второй мировой войны
  7. Na-катионирование воды второй ступени
  8. Na-катионирование воды первой ступени
  9. Административно-территориальные реформы в Казахстане во второй половине XIX в.
  10. Алгоритм оказания первой помощи при родах.
  11. Аль-Фараби: «Второй учитель»
  12. Аптечка первой помощи.

Цель работы. Развить навыки объектно-ориентированного программирования, использовав для реализации задачи про интерпретатор механизмы инкапсуляции, наследования, полиморфизма, динамического связывания и виртуальных функций.

Усовершенствовать интерпретатор математических выражений (см. лаб.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 double rezult(void) {}
virtual Telement* copy(void) {}
virtual Telement* differ(void) {}

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.


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.015 сек.)