Oбъектно-ориентированная реализация числовых функций
Цель лекции: Научить создавать классы, для описания функций и реализации операций над функциями.
Пусть и
- произвольные множества. Мы под абстрактной функцией
будем понимать правило, которое элементу
множества
сопоставляет элемент множества
. Записывается это
в виде
![F:X\to Y.](/sites/default/files/tex_cache/3e36e8dcd1577fb72de2220b240fb89b.png)
![Y](/sites/default/files/tex_cache/57cec4137b614c87cb4e24a3d003a3e0.png)
![Y](/sites/default/files/tex_cache/57cec4137b614c87cb4e24a3d003a3e0.png)
![F](/sites/default/files/tex_cache/800618943025315f869e4e1f09471012.png)
![X](/sites/default/files/tex_cache/02129bb861061d1a052c592e2dc6b383.png)
![D\subset X](/sites/default/files/tex_cache/9174a4a82e427bd986a5e7e3d781620f.png)
![D](/sites/default/files/tex_cache/f623e75af30e62bbd73d6df5b50bb7b5.png)
![F](/sites/default/files/tex_cache/800618943025315f869e4e1f09471012.png)
Мы будем рассматривать функции , определенные на подмножествах
. Однако в качестве множества
у нас могут выступать
различные множества. Для этого создадим универсальный класс,
который сможет представлять любые другие объекты.
![\begin{verbatim}
class TElement
{
object A; // место для любого объекта
public TElement(object A)
{
SetA(A);
}
public object GetA()
{
return A;
}
public void SetA(object A)
{
this.A = A;
}
}
\end{verbatim}](/sites/default/files/tex_cache/e495350da0e88109685b7d0c8672113e.png)
Заметим, что мы воспользовались типом . Этот тип является
родительским для всех объектов C#, поэтому возможно в классе
хранить ссылку на любой объект (элемент множества
).
Абстрактный класс представляющий функцию, заданную на некотором
отрезке , выглядит следующим образом
![\begin{verbatim}
abstract class TAFunc
{
protected double a, b;
public TAFunc(double a, double b)
{
this.a = a;
this.b = b;
}
public double Get_a()
{
return a;
}
public double Get_b()
{
return b;
}
public TElement Calc(double x)
{
if ((x < a) || (x > b))
{
return null;
}
else
{
return CalcVal(x);
}
}
protected abstract TElement CalcVal(double x);
}
\end{verbatim}](/sites/default/files/tex_cache/b01772169cb4a7512c7701cf23eee625.png)
![CalcVal](/sites/default/files/tex_cache/e5ee4e992e47c379adac3aa37e3c8723.png)
![Y](/sites/default/files/tex_cache/57cec4137b614c87cb4e24a3d003a3e0.png)
![\Bbb{R}](/sites/default/files/tex_cache/9d620c36f447d35915bc6cdd1167f319.png)
![TAFunc](/sites/default/files/tex_cache/35bc081b8b5d872a9bba0c3e12bbd95a.png)
![\begin{verbatim}
abstract class TRFunc : TAFunc
{
public TRFunc(double a, double b) : base(a, b) { }
public double CalcY(double x)
{
return (double)Calc(x).GetA();
}
}
\end{verbatim}](/sites/default/files/tex_cache/73f019aca8ded311e37afbf53e677115.png)
![CalcY](/sites/default/files/tex_cache/5d94c7a56ea7137f43dfd776227adab5.png)
![double](/sites/default/files/tex_cache/e8cd7da078a86726031ad64f35f5a6c0.png)
![object](/sites/default/files/tex_cache/a8cfde6331bd59eb2ac96f8911c4b666.png)
Покажем как выглядит класс для описания функции .
![\begin{verbatim}
class TSinFunc : TRFunc
{
public TSinFunc(double a, double b) : base(a, b) { }
protected override TElement CalcVal(double x)
{
TElement res = new TElement(Math.Sin(x));
return res;
}
}
\end{verbatim}](/sites/default/files/tex_cache/d53a6e2d991aa43a8e4e0944c63ef085.png)
Теперь покажем, как с помощью объектно-ориентированного подхода можно выполнять различные операции над функциями. Создадим класс, который будет представлять собой производную от исходного класса-функции.
![\begin{verbatim}
class TDiffFunc : TRFunc
{
protected TRFunc Func;
double h;
public TDiffFunc(TRFunc Func, double h)
: base(Func.Get_a(), Func.Get_b())
{
this.Func = Func;
this.h = h;
}
protected override TElement CalcVal(double x)
{
TElement res = new TElement(0);
double D;
if ((x + h) <= b)
{
D = (Func.CalcY(x + h) - Func.CalcY(x)) / h;
}
else
{
D = (Func.CalcY(x) - Func.CalcY(x - h)) / h;
}
res.SetA(D);
return res;
}
}
\end{verbatim}](/sites/default/files/tex_cache/f6bc3993fa351d9b6db837c40bf54bcb.png)
Теперь с использованием наших классов мы вычислим производные от
функции .
![\begin{verbatim}
TSinFunc Sin = new TSinFunc(0, 2.0 * Math.PI);
TDiffFunc DSin = new TDiffFunc(Sin, 0.00001);
TDiffFunc D2Sin = new TDiffFunc(DSin, 0.0001);
double x0 = Math.PI / 2.0;
Console.WriteLine("DSin({0}) = {1}", x0, DSin.CalcY(x0));
Console.WriteLine("D2Sin({0}) = {1}", x0, D2Sin.CalcY(x0));
\end{verbatim}](/sites/default/files/tex_cache/b2461e2edf0142799efb67466582feaf.png)
![\begin{verbatim}
DSin(1.5707963267949) = -5.00000041370186E-06
D2Sin(1.5707963267949) = -0.999999971718068
\end{verbatim}](/sites/default/files/tex_cache/8ff9be3c1ef2ef4fafaf9e4cc13de5e8.png)
![0](/sites/default/files/tex_cache/cfcd208495d565ef66e7dff9f98764da.png)
![-1](/sites/default/files/tex_cache/6bb61e3b7bce0931da574d19d1d82c88.png)
Мы реализовали класс для представления функций, убедились, что
наши классы в состоянии выполнять различные действия с функциями.
Однако в наших вычислениях мы использовали тип для
представления действительных чисел. Этот подход означает, что мы
рассматриваем лишь подмножество рациональных чисел. Но из прошлой
лекции мы знаем, что на компьютере можно реализовать и большее ---
машина Поста (а значит теоретически и любой компьютер) может
оперировать конструктивными действительными числами. Поэтому
естественно рассматривать функции как отображение одного
конструктивного действительного числа в другое конструктивное
действительное число. В конструктивной математике есть
фундаментальное понятие - конструктивная функция. Однако,
как известно, единого определения конструктивной функции в строгих
рамках конструктивной математики не существует.
Мы дадим определение функции Маркова. Но сначала мы должны
ответить на естественный вопрос - а какие конструктивные
действительные числа называются равными? Если исходить из того,
что конструктивно действительное число - это пара алгоритмов, то
из неравенства этих алгоритмов еще не следует неравенство
конструктивных действительных чисел. Поэтому мы будем говорить,
что равно
и писать
, если существует такая вычислимая
функция
, что
![|x(n)-y(n)|<\varepsilon,](/sites/default/files/tex_cache/df9c895ea8604725a48895bcc2f3dfb9.png)
![n>r(\varepsilon)](/sites/default/files/tex_cache/9ff1ab56c4ca67297aaade098f0daf29.png)
Пусть - некоторое множество конструктивных действительных
чисел такое, что если
и
- другое конструктивное
действительное число и
, то
. Конструктивной функцией
или функцией Маркова называется такой алгоритм
, что
- Для любого
определено
и
есть конструктивное действительное число.
- Если
и
суть конструктивные действительные числа,
и
, то
.
Ключевые термины
Абстрактная функция - однозначное отображение одно множества в другое.
Конструктивная функция - алгоритм сопоставляющий одному конструктивному действительному числу другое конструктивное действительное число.
Область определения функции - множество на, котором определена функция.
Краткие итоги: Реализован абстрактный класс на языке C#, реализующий функции. Разработаны классы, реализующие конкретные числовые функции и операции над ними.