16223

Динамическое создание объектов на базе стандартных классов DELPHI

Лабораторная работа

Информатика, кибернетика и программирование

Лабораторная работа №12 Динамическое создание объектов на базе стандартных классов DELPHI Цель работы: Изучить принципы создания COMсервера и COMприложения Постановка задачи: Разработать COMсервер реализующий три метода решения нелинейных уравнений. Разработать COMкл...

Русский

2013-06-20

128.5 KB

5 чел.

Лабораторная работа №12

Динамическое создание объектов на базе стандартных классов DELPHI

Цель работы: Изучить принципы создания COM-сервера и COM-приложения

Постановка задачи: Разработать COM-сервер, реализующий три метода решения нелинейных уравнений. Разработать COM-клиент решения нелинейных уравнений различными методами

Краткие теоретические сведения:

Модель объектных компонентов – (COM, Component Object Model) является производственным стандартом Microsoft для обмена информацией между приложениями. Основная идея – обмен информацией независимо от языка написания приложения. Обычно COM-объекты представлены в виде EXE или DLL – файлов. Если выполнять Com-объект, находящийся на одном компьютере, с помощью процессорного времени второго компьютера, а результаты отправлять на третий компьютер – это не что иное, как распределенная модель COM (Distributed COMDCOM).

Для получения ссылки на COM-объект, используйте функцию CreateComObject(GUID). Получить всю информацию о зарегистрированном в реестре объекте COM, можно в соответствующей ветви раздела реестра HKEY_CLASSES_ROOT.

Когда приложение-клиент вызывает функцию CreateComObject(GUID), то он дает команду операционной системе создать экземпляр зарегистрированного класса. ОС просматривает реестр в поисках GUID этого класса, после чего возвращает ссылку в вызывающую программу и запускает приложение-сервер. Теперь можно обращаться к методам и свойствам COM-приложения как к собственным.

Текст программы:

UMainForm:

unit UMainForm;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, StdCtrls, ExtCtrls, ComCtrls, TeeProcs, TeEngine, Chart, Series,

 Buttons, UIEquation, BubbleCh, ComObj;

type

 TForm1 = class(TForm)

   EditMin: TEdit;

   EditMax: TEdit;

   RadioGroup1: TRadioGroup;

   EditEpsilon: TEdit;

   Label1: TLabel;

   Label2: TLabel;

   Label3: TLabel;

   Panel1: TPanel;

   Label4: TLabel;

   Label5: TLabel;

   Panel2: TPanel;

   Bevel1: TBevel;

   Label6: TLabel;

   Panel3: TPanel;

   Label7: TLabel;

   EditResult: TEdit;

   CheckBox1: TCheckBox;

   UpDown1: TUpDown;

   EditRound: TEdit;

   DisplayChart: TChart;

   Series1: TLineSeries;

   Series2: TPointSeries;

   SpeedButton1: TSpeedButton;

   CheckBox2: TCheckBox;

   SpeedButton2: TSpeedButton;

   Panel4: TPanel;

   Series3: TFastLineSeries;

   EditDelay: TEdit;

   UpDown2: TUpDown;

   Label8: TLabel;

   RadioGroup2: TRadioGroup;

   procedure CheckBox1Click(Sender: TObject);

   procedure SpeedButton1Click(Sender: TObject);

   procedure Wait(x: double);

   procedure EditRoundChange(Sender: TObject);

   procedure FormCreate(Sender: TObject);

   procedure SpeedButton2Click(Sender: TObject);

   procedure EditEpsilonKeyPress(Sender: TObject; var Key: Char);

   procedure CheckBox2Click(Sender: TObject);

   procedure EditDelayChange(Sender: TObject);

   procedure RadioGroup2Click(Sender: TObject);

   procedure RadioGroup1Click(Sender: TObject);

   procedure FormClose(Sender: TObject; var Action: TCloseAction);

 private

   { Private declarations }

 public

   { Public declarations }

 end;

type

 TCalculationThread = class(TThread)

 private

   { Private declarations }

   FMessage: string;

 protected

   procedure Execute; override;

   procedure Mess;

 end;

var

 Form1: TForm1;

 e: IEquation;

 s: TCalculationThread;

 delayTime: integer=500;

implementation

{$R *.dfm}

procedure TCalculationThread.Execute;

begin

 { Place thread code here }

 try

   try

     e.Calculate;

   except

     on e1: Exception do

             begin

               FMessage:=e1.Message;

               Synchronize(Mess);

             end;

   end;

 finally

   Form1.CheckBox1Click(Form1.CheckBox1);  //Просто запись значения в EditResult с учётом округлять/не округлять

   Self.Terminate;

   Form1.SpeedButton1.Enabled:=true;

   Form1.SpeedButton2.Enabled:=false;

   Form1.Panel4.Enabled:=true;

   Self.Free;

 end;

end;

procedure TCalculationThread.Mess;

begin

 MessageDlg(FMessage, mtWarning, [mbOK], 0);

end;

procedure TForm1.CheckBox1Click(Sender: TObject);

begin

 EditRound.Enabled:=(Sender as TCheckBox).Checked;

 UpDown1.Enabled:=(Sender as TCheckBox).Checked;

 try

   if (Sender as TCheckBox).Checked then

     EditResult.Text:=FloatToStrF(e.Res, ffFixed, 15, StrToInt(EditRound.Text))

   else

     EditResult.Text:=FloatToStrF(e.Res, ffFixed, 15, 15);

 finally

 end;

end;

procedure TForm1.SpeedButton1Click(Sender: TObject);

begin

 try

   e.Min:=StrToFloat(EditMin.Text);

   e.Max:=StrToFloat(EditMax.Text);

   e.Epsilon:=StrToFloat(EditEpsilon.Text);

   e.Method:=RadioGroup1.ItemIndex;

 except

   on e1: ECantBeZero do

             begin

               MessageDlg(e1.Message, mtWarning, [mbOK], 0);

               exit;

             end;

   else

             begin

               MessageDlg('Неверное число!'#13#10'Проверьте, возможно в одно из полей введено не число!', mtError, [mbOK], 0);

               exit;

             end;

 end;

 SpeedButton1.Enabled:=false;

 SpeedButton2.Enabled:=true;

 Panel4.Enabled:=false;

 s:=TCalculationThread.Create(false);

end;

procedure TForm1.Wait(x: double);

begin

 if CheckBox2.Checked then

   sleep(delayTime);

end;

procedure TForm1.EditRoundChange(Sender: TObject);

begin

 CheckBox1Click(CheckBox1);

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

try

 e:=(CreateComObject(Class_Equation) as IEquation);

 e.Chart:=DisplayChart;

 e.SetNewEquation(0, 0.5, 2, 0.001, RadioGroup1.ItemIndex);

 e.Calculate;

 e.OnNextStep:=Wait;

 CheckBox1Click(CheckBox1); //Просто запись значения в EditResult с учётом округлять/не округлять

 Panel4.Enabled:=true;

 SpeedButton1.Enabled:=true;

 CheckBox1.Enabled:=true;

except

end;

end;

procedure TForm1.SpeedButton2Click(Sender: TObject);

begin

 if s.Suspended then

   s.Resume

 else

   s.Suspend;

end;

procedure TForm1.EditEpsilonKeyPress(Sender: TObject; var Key: Char);

begin

 if not (Key in ['0'..'9', ',', '-', #8]) then

   Key:=chr(0);

end;

procedure TForm1.CheckBox2Click(Sender: TObject);

begin

 EditDelay.Enabled:=(Sender as TCheckBox).Checked;

 UpDown2.Enabled:=(Sender as TCheckBox).Checked;

end;

procedure TForm1.EditDelayChange(Sender: TObject);

begin

 delayTime:=StrToInt((Sender as TEdit).Text);

end;

procedure TForm1.RadioGroup2Click(Sender: TObject);

begin

 case (Sender as TRadioGroup).ItemIndex of

 0:  begin

       //e.Free;

       e.SetNewEquation(0, 0.5, 2, 0.001, RadioGroup1.ItemIndex);

       e.OnNextStep:=nil;

       EditMin.Text:='0,5';

       EditMax.Text:='2';

       EditEpsilon.Text:='0,001';

       e.Calculate;

       CheckBox1Click(CheckBox1);

       e.OnNextStep:=Wait;

     end;

 1:  begin

       //e.Free;

       e.SetNewEquation(1, 2, 3, 0.001, RadioGroup1.ItemIndex);

       e.OnNextStep:=nil;

       EditMin.Text:='2';

       EditMax.Text:='3';

       EditEpsilon.Text:='0,001';

       e.Calculate;

       CheckBox1Click(CheckBox1);

       e.OnNextStep:=Wait;

     end;

 2:  begin

       //e.Free;

       e.SetNewEquation(2, 2, 3, 0.001, RadioGroup1.ItemIndex);

       e.OnNextStep:=nil;

       EditMin.Text:='2';

       EditMax.Text:='3';

       EditEpsilon.Text:='0,001';

       e.Calculate;

       CheckBox1Click(CheckBox1);

       e.OnNextStep:=Wait;

     end;

 end;

end;

procedure TForm1.RadioGroup1Click(Sender: TObject);

begin

{  e.OnNextStep:=nil;

 e.Method:=RadioGroup1.ItemIndex;

 e.Calculate;

 CheckBox1Click(CheckBox1);

 e.OnNextStep:=Wait;

 }

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

 //e.FreeSelf;

 //Action:=caNone;

end;

end.

UIEquation:

unit UIEquation;

interface

uses SysUtils, Chart;

const

 Class_Equation: TGUID = '{C38FF40B-9B73-45AC-808C-D2633A4D25F0}';

 IID_IEquation: TGUID = '{8F0B1F0B-6D2D-4AE9-95DA-B571A5F8BA9D}';

const drawFSteps=50;

     drawFSpace=0.05;

     FMaxIterations=100;

type

 EMinNotLessThenMax=class(Exception);

 ETooMuchIterations=class(Exception);

 EDontMatchCondition=class(Exception);

 EZeroDenominator=class(Exception);

 EZeroDerivatite=class(Exception);

 ECantBeZero=class(Exception);

type

 TNextStepEvent=procedure(x: double) of object;

type

 IEquation=interface (IUnknown)

 ['{8F0B1F0B-6D2D-4AE9-95DA-B571A5F8BA9D}']

   function GetMin: Double;

   procedure SetMin(const Value: Double);

   function GetChart: TChart;

   function GetEpsilon: Double;

   function GetMax: Double;

   function GetMethod: integer;

   function GetOnNextStep: TNextStepEvent;

   function GetResult: Double;

   procedure SetChart(const Value: TChart);

   procedure SetMax(const Value: Double);

   procedure SetMethod(const Value: integer);

   procedure SetOnNextStep(const Value: TNextStepEvent);

   procedure SetEpsilon(AEpsilon: double);

   procedure SetNewEquation(AEquation: integer; AMin, AMax, AEpsilon: double; AMethod: integer);

   property Min: Double read GetMin write SetMin;

   property Max: Double read GetMax write SetMax;

   property Epsilon: Double read GetEpsilon write SetEpsilon;

   property Res: Double read GetResult;

   property Method: integer read GetMethod write SetMethod;

   property Chart: TChart read GetChart write SetChart;

   property OnNextStep: TNextStepEvent read GetOnNextStep write SetOnNextStep;

   procedure Calculate;

 end;

implementation

end.

UEquation:

unit UEquation;

interface

uses SysUtils, Chart, Math, UIEquation;

type

 TEquation=class (TInterfacedObject, IEquation)

 private

   FMin: Double;

   FMax: Double;

   FEpsilon: Double;

   FResult: Double;

   FMethod: Integer;

   FOnNextStep: TNextStepEvent;

   FChart: TChart;

   FEquation: Integer;

   function GetMin: Double;

   procedure SetMin(const Value: Double);

   function GetChart: TChart;

   function GetEpsilon: Double;

   function GetMax: Double;

   function GetMethod: integer;

   function GetOnNextStep: TNextStepEvent;

   function GetResult: Double;

   procedure SetChart(const Value: TChart);

   procedure SetMax(const Value: Double);

   procedure SetMethod(const Value: integer);

   procedure SetOnNextStep(const Value: TNextStepEvent);

 public

   constructor Create; overload;

   constructor Create(AMin, AMax, AEpsilon: double; AMethod: integer; AChart: TChart); overload;

   function F(x: Double): Double; virtual;

   function Phi(x: Double): Double; virtual;

   function FirstDerivative(x: Double): Double; virtual;

   function SecondDerivative(x: Double): Double; virtual;

   function F1(x: Double): Double; virtual;

   function Phi1(x: Double): Double; virtual;

   function FirstDerivative1(x: Double): Double; virtual;

   function SecondDerivative1(x: Double): Double; virtual;

   function F2(x: Double): Double; virtual;

   function Phi2(x: Double): Double; virtual;

   function FirstDerivative2(x: Double): Double; virtual;

   function SecondDerivative2(x: Double): Double; virtual;

   function F3(x: Double): Double; virtual;

   function Phi3(x: Double): Double; virtual;

   function FirstDerivative3(x: Double): Double; virtual;

   function SecondDerivative3(x: Double): Double; virtual;

   procedure SetEpsilon(AEpsilon: double); virtual;

   property Min: Double read GetMin write SetMin;

   property Max: Double read GetMax write SetMax;

   property Epsilon: Double read GetEpsilon write SetEpsilon;

   property Res: Double read GetResult;

   property Method: integer read GetMethod write SetMethod;

   property Chart: TChart read GetChart write SetChart;

   property OnNextStep: TNextStepEvent read GetOnNextStep write SetOnNextStep;

   procedure Calculate; virtual;

   function Calculate_HalfDividing: Double; virtual;

   function Calculate_Iterations: Double; virtual;

   function Calculate_Newton: Double; virtual;

   procedure DrawF; virtual;

   procedure DrawStep(x: double); virtual;

   procedure DrawStep2(x: double); virtual;

   procedure SetNewEquation(AEquation: integer; AMin, AMax, AEpsilon: double; AMethod: integer);

 end;

implementation

//TEquation1

 function TEquation.F2(x: Double): Double;

 begin

   Result:=3*sin(sqrt(x))+0.35*x-3.8;

   //Self.Free;

 end;

 function TEquation.Phi2(x: Double): Double;

 begin

   Result:=-8.571*sin(sqrt(x))+10.8571;

 end;

 function TEquation.FirstDerivative2(x: Double): Double;

 begin

   Result:=1.5*cos(sqrt(x))/sqrt(x)+0.35;

 end;

 function TEquation.SecondDerivative2(x: Double): Double;

 begin

   Result:=-0.75*(sin(sqrt(x))+cos(sqrt(x)))/(x*sqrt(x));

 end;

//TEquation1

 function TEquation.F3(x: Double): Double;

 begin

   Result:=ln(x)-x+1.8;

 end;

 function TEquation.Phi3(x: Double): Double;

 begin

   Result:=ln(x)+1.8;

 end;

 function TEquation.FirstDerivative3(x: Double): Double;

 begin

   Result:=1/x-1;

 end;

 function TEquation.SecondDerivative3(x: Double): Double;

 begin

   Result:=-1/sqr(x);

 end;

//TEquation

 constructor TEquation.Create;

 begin

   inherited Create;

   FMin:=0;

   FMax:=2;

   FEpsilon:=0.001;

 end;

 constructor TEquation.Create(AMin, AMax, AEpsilon: double; AMethod: integer; AChart: TChart);

 begin

   inherited Create;

   FMin:=AMin;

   FMax:=AMax;

   FEpsilon:=AEpsilon;

   FMethod:=AMethod;

   FChart:=AChart;

   DrawF;

 end;

 procedure TEquation.SetEpsilon(AEpsilon: double);

 begin

   if (AEpsilon=0) then

     raise ECantBeZero.Create('Точность не может равняться 0!');

     FEpsilon:=abs(AEpsilon);

 end;

 procedure TEquation.Calculate;

 begin

   if not (FMin<FMax) then

     raise EMinNotLessThenMax.Create('Нижняя граница должна быть меньше верхней!');

   if assigned(FChart) then

   begin

     FChart.Series[1].Clear;

     FChart.Series[2].Clear;

   end;

   case FMethod of

   1: FResult:=Calculate_Iterations;

   2: FResult:=Calculate_Newton;

   else

      FResult:=Calculate_HalfDividing;

   end;

 end;

 procedure TEquation.DrawF;

 var

   leftBorder, rightBorder, h, x: double;

   i: integer;

 begin

   if assigned(FChart) then

   begin

     FChart.Series[0].Clear;

     leftBorder:=FMin-(FMax-Fmin)*drawFSpace;

     rightBorder:=FMax+(FMax-Fmin)*drawFSpace;

     h:=(rightBorder-leftBorder)/drawFSteps;

     x:=leftBorder;

     for i:=0 to drawFSteps do

     begin

       FChart.Series[0].AddXY(x, f(x));

       x:=x+h;

     end;

   end;

 end;

 function TEquation.F1(x: Double): Double;

 begin

   Result:=0.25*power(x, 3)+x-1.2502;

 end;

 function TEquation.Phi1(x: Double): Double;

 begin

   Result:=-0.25*power(x, 3)+1.2502;

 end;

 function TEquation.FirstDerivative1(x: Double): Double;

 begin

   Result:=0.75*power(x, 2)+1;

 end;

 function TEquation.SecondDerivative1(x: Double): Double;

 begin

   Result:=1.5*x+1;

 end;

 function TEquation.Calculate_HalfDividing: Double;

 var B, A, x0: double;

     N: integer;

 begin

   if not (F(FMin)*F(FMax)<0) then

     raise EDontMatchCondition.Create('Для метода половинного деления необходимо, чтобы функция на концах промежутка иммела разные знаки!');

   N:=0;

   B:=FMax;

   A:=FMin;

   if F(A)=0 then

   begin

     Result:=A;

     DrawStep(A);

     exit;

   end;

   if F(B)=0 then

   begin

     Result:=B;

     DrawStep(B);

     exit;

   end;

   while ((B-A)>(FEpsilon*2)) do

   begin

     if N>FMaxIterations then

       raise ETooMuchIterations.Create('Превышено максимальное количество итераций ('+inttostr(FMaxIterations)+')!');

     x0:=(B+A)/2;

     if F(x0)=0 then

       break;

     DrawStep(x0);

     if (F(A)*F(x0)<0) then

       B:=x0

     else

       A:=x0;

     inc(N);

     if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(x0);

     end;

     if Assigned(FOnNextStep) then

       FOnNextStep(x0);

   end;

   Result:=(B+A)/2;

   if Assigned(FChart) then

   begin

       FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

       FChart.Series[1].Title:='X='+FloatToStr(Result);

   end;

 end;

 function TEquation.Calculate_Iterations: Double;

 var N: integer;

     x0, x1{, x2, y0, y1, y2, d1, d2}: double;

 begin

    N:=1;

    x1:=(FMax+FMin)/2;

    DrawStep(x1);

    repeat

     x0:=x1;

      if N>FMaxIterations then

       raise ETooMuchIterations.Create('Превышено максимальное количество итераций ('+inttostr(FMaxIterations)+')!');

     inc(N);

     x1:=Phi(x0);

     DrawStep(x1);

     if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(x1);

     end;

     if Assigned(FOnNextStep) then

       FOnNextStep(x1);

    until ((x1-x0)<FEpsilon);

    Result:=x1;

 end;

 function TEquation.Calculate_Newton: Double;

 var N: integer;

     x0, x1, d: double;

 begin

   N:=1;

   x1:=FMin;

   if F(FMax)*SecondDerivative(FMax)>0 then

     x1:=FMax;

   DrawStep2(x1);

   if Assigned(FOnNextStep) then

       FOnNextStep(x1);

   repeat

     if N>FMaxIterations then

       raise ETooMuchIterations.Create('Превышено максимальное количество итераций ('+inttostr(FMaxIterations)+')!');

     x0:=x1;

     if FirstDerivative(X0)=0 then

       raise EZeroDerivatite.Create('На шаге '+inttostr(N)+' производная стала равна нулю!');

     x1:=x0-(F(x0)/FirstDerivative(X0));

     DrawStep2(x1);

     inc(N);

     if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(x1);

     end;

     if Assigned(FOnNextStep) then

       FOnNextStep(x1);

     if abs(x1)>1 then

       d:=(x1-x0)/x1

     else

       d:=x1-x0;

   until ((d<=FEpsilon) and (abs(F(x1))<=100*Fepsilon));

   Result:=x1;

   if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(Result);

     end;

 end;

 procedure TEquation.DrawStep(x: Double);

 begin

   if Assigned(FChart) then

     FChart.Series[1].AddXY(x, F(x));

 end;

 procedure TEquation.DrawStep2(x: Double);

 begin

   if Assigned(FChart) then

   begin

     if ((F(x)<0) and (FirstDerivative(x)>0)) then

     begin

       FChart.Series[1].AddXY(x, F(x));

       FChart.Series[2].AddXY(x, 0);

       FChart.Series[2].AddXY(x, F(x));

     end

     else

     begin

       FChart.Series[1].AddXY(x, F(x));

       FChart.Series[2].AddXY(x, F(x));

       FChart.Series[2].AddXY(x, 0);

     end

   end;

 end;

function TEquation.F(x: Double): Double;

begin

 case FEquation of

   1: Result:=F2(x);

   2: Result:=F3(x);

   else Result:=F1(x);

 end;

end;

function TEquation.FirstDerivative(x: Double): Double;

begin

 case FEquation of

   1: Result:=FirstDerivative2(x);

   2: Result:=FirstDerivative3(x);

   else Result:=FirstDerivative1(x);

 end;

end;

function TEquation.Phi(x: Double): Double;

begin

 case FEquation of

   1: Result:=Phi2(x);

   2: Result:=Phi3(x);

   else Result:=Phi1(x);

 end;

end;

function TEquation.SecondDerivative(x: Double): Double;

begin

 case FEquation of

   1: Result:=SecondDerivative2(x);

   2: Result:=SecondDerivative3(x);

   else Result:=SecondDerivative1(x);

 end;

end;

procedure TEquation.SetNewEquation(AEquation: integer; AMin, AMax,

 AEpsilon: double; AMethod: integer);

begin

   FEquation:=AEquation;

   FMin:=AMin;

   FMax:=AMax;

   FEpsilon:=AEpsilon;

   FMethod:=AMethod;

   DrawF;

end;

function TEquation.GetMin: Double;

begin

 Result:=FMin;

end;

procedure TEquation.SetMin(const Value: Double);

begin

 FMin:=Value;

end;

function TEquation.GetChart: TChart;

begin

 Result:=FChart;

end;

function TEquation.GetEpsilon: Double;

begin

 Result:=FEpsilon;

end;

function TEquation.GetMax: Double;

begin

 Result:=FMax;

end;

function TEquation.GetMethod: integer;

begin

 Result:=FMethod;

end;

function TEquation.GetOnNextStep: TNextStepEvent;

begin

 Result:=FOnNextStep;

end;

function TEquation.GetResult: Double;

begin

 Result:=FResult;

end;

procedure TEquation.SetChart(const Value: TChart);

begin

 FChart:=Value;

end;

procedure TEquation.SetMax(const Value: Double);

begin

 FMax:=Value;

end;

procedure TEquation.SetMethod(const Value: integer);

begin

 FMethod:=Value;

end;

procedure TEquation.SetOnNextStep(const Value: TNextStepEvent);

begin

 FOnNextStep:=Value;

end;

end.

UEquation_COM:

unit UEquation_COM;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses

 Windows, ActiveX, Classes, ComObj, UIEquation, Chart, Math, SysUtils;

type

 TEquation=class (TComObject, IEquation)

 private

   FMin: Double;

   FMax: Double;

   FEpsilon: Double;

   FResult: Double;

   FMethod: Integer;

   FOnNextStep: TNextStepEvent;

   FChart: TChart;

   FEquation: Integer;

 public

   constructor Create; overload;

   constructor Create(AMin, AMax, AEpsilon: double; AMethod: integer; AChart: TChart); overload;

   function F(x: Double): Double; virtual;

   function Phi(x: Double): Double; virtual;

   function FirstDerivative(x: Double): Double; virtual;

   function SecondDerivative(x: Double): Double; virtual;

   function F1(x: Double): Double; virtual;

   function Phi1(x: Double): Double; virtual;

   function FirstDerivative1(x: Double): Double; virtual;

   function SecondDerivative1(x: Double): Double; virtual;

   function F2(x: Double): Double; virtual;

   function Phi2(x: Double): Double; virtual;

   function FirstDerivative2(x: Double): Double; virtual;

   function SecondDerivative2(x: Double): Double; virtual;

   function F3(x: Double): Double; virtual;

   function Phi3(x: Double): Double; virtual;

   function FirstDerivative3(x: Double): Double; virtual;

   function SecondDerivative3(x: Double): Double; virtual;

   function GetMin: Double;

   procedure SetMin(const Value: Double);

   function GetChart: TChart;

   function GetEpsilon: Double;

   function GetMax: Double;

   function GetMethod: integer;

   function GetOnNextStep: TNextStepEvent;

   function GetResult: Double;

   procedure SetChart(const Value: TChart);

   procedure SetMax(const Value: Double);

   procedure SetMethod(const Value: integer);

   procedure SetOnNextStep(const Value: TNextStepEvent);

   

   procedure SetEpsilon(AEpsilon: double); virtual;

   property Min: Double read GetMin write SetMin;

   property Max: Double read GetMax write SetMax;

   property Epsilon: Double read GetEpsilon write SetEpsilon;

   property Res: Double read GetResult;

   property Method: integer read GetMethod write SetMethod;

   property Chart: TChart read GetChart write SetChart;

   property OnNextStep: TNextStepEvent read GetOnNextStep write SetOnNextStep;

   procedure Calculate; virtual;

   function Calculate_HalfDividing: Double; virtual;

   function Calculate_Iterations: Double; virtual;

   function Calculate_Newton: Double; virtual;

   procedure DrawF; virtual;

   procedure DrawStep(x: double); virtual;

   procedure DrawStep2(x: double); virtual;

   procedure SetNewEquation(AEquation: integer; AMin, AMax, AEpsilon: double; AMethod: integer);

 end;

implementation

uses ComServ;

//TEquation1

 function TEquation.F2(x: Double): Double;

 begin

   Result:=3*sin(sqrt(x))+0.35*x-3.8;

   //Self.Free;

 end;

 function TEquation.Phi2(x: Double): Double;

 begin

   Result:=-8.571*sin(sqrt(x))+10.8571;

 end;

 function TEquation.FirstDerivative2(x: Double): Double;

 begin

   Result:=1.5*cos(sqrt(x))/sqrt(x)+0.35;

 end;

 function TEquation.SecondDerivative2(x: Double): Double;

 begin

   Result:=-0.75*(sin(sqrt(x))+cos(sqrt(x)))/(x*sqrt(x));

 end;

//TEquation1

 function TEquation.F3(x: Double): Double;

 begin

   Result:=ln(x)-x+1.8;

 end;

 function TEquation.Phi3(x: Double): Double;

 begin

   Result:=ln(x)+1.8;

 end;

 function TEquation.FirstDerivative3(x: Double): Double;

 begin

   Result:=1/x-1;

 end;

 function TEquation.SecondDerivative3(x: Double): Double;

 begin

   Result:=-1/sqr(x);

 end;

//TEquation

 constructor TEquation.Create;

 begin

   inherited Create;

   FMin:=0;

   FMax:=2;

   FEpsilon:=0.001;

 end;

 constructor TEquation.Create(AMin, AMax, AEpsilon: double; AMethod: integer; AChart: TChart);

 begin

   inherited Create;

   FMin:=AMin;

   FMax:=AMax;

   FEpsilon:=AEpsilon;

   FMethod:=AMethod;

   FChart:=AChart;

   DrawF;

 end;

 procedure TEquation.SetEpsilon(AEpsilon: double);

 begin

   if (AEpsilon=0) then

     raise ECantBeZero.Create('Точность не может равняться 0!');

     FEpsilon:=abs(AEpsilon);

 end;

 procedure TEquation.Calculate;

 begin

   if not (FMin<FMax) then

     raise EMinNotLessThenMax.Create('Нижняя граница должна быть меньше верхней!');

   if assigned(FChart) then

   begin

     FChart.Series[1].Clear;

     FChart.Series[2].Clear;

   end;

   case FMethod of

   1: FResult:=Calculate_Iterations;

   2: FResult:=Calculate_Newton;

   else

      FResult:=Calculate_HalfDividing;

   end;

 end;

 procedure TEquation.DrawF;

 var

   leftBorder, rightBorder, h, x: double;

   i: integer;

 begin

   if assigned(FChart) then

   begin

     FChart.Series[0].Clear;

     leftBorder:=FMin-(FMax-Fmin)*drawFSpace;

     rightBorder:=FMax+(FMax-Fmin)*drawFSpace;

     h:=(rightBorder-leftBorder)/drawFSteps;

     x:=leftBorder;

     for i:=0 to drawFSteps do

     begin

       FChart.Series[0].AddXY(x, f(x));

       x:=x+h;

     end;

   end;

 end;

 function TEquation.F1(x: Double): Double;

 begin

   Result:=0.25*power(x, 3)+x-1.2502;

 end;

 function TEquation.Phi1(x: Double): Double;

 begin

   Result:=-0.25*power(x, 3)+1.2502;

 end;

 function TEquation.FirstDerivative1(x: Double): Double;

 begin

   Result:=0.75*power(x, 2)+1;

 end;

 function TEquation.SecondDerivative1(x: Double): Double;

 begin

   Result:=1.5*x+1;

 end;

 function TEquation.Calculate_HalfDividing: Double;

 var B, A, x0: double;

     N: integer;

 begin

   if not (F(FMin)*F(FMax)<0) then

     raise EDontMatchCondition.Create('Для метода половинного деления необходимо, чтобы функция на концах промежутка иммела разные знаки!');

   N:=0;

   B:=FMax;

   A:=FMin;

   if F(A)=0 then

   begin

     Result:=A;

     DrawStep(A);

     exit;

   end;

   if F(B)=0 then

   begin

     Result:=B;

     DrawStep(B);

     exit;

   end;

   while ((B-A)>(FEpsilon*2)) do

   begin

     if N>FMaxIterations then

       raise ETooMuchIterations.Create('Превышено максимальное количество итераций ('+inttostr(FMaxIterations)+')!');

     x0:=(B+A)/2;

     if F(x0)=0 then

       break;

     DrawStep(x0);

     if (F(A)*F(x0)<0) then

       B:=x0

     else

       A:=x0;

     inc(N);

     if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(x0);

     end;

     if Assigned(FOnNextStep) then

       FOnNextStep(x0);

   end;

   Result:=(B+A)/2;

   if Assigned(FChart) then

   begin

       FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

       FChart.Series[1].Title:='X='+FloatToStr(Result);

   end;

 end;

 function TEquation.Calculate_Iterations: Double;

 var N: integer;

     x0, x1{, x2, y0, y1, y2, d1, d2}: double;

 begin

    N:=1;

    x1:=(FMax+FMin)/2;

    DrawStep(x1);

    repeat

     x0:=x1;

      if N>FMaxIterations then

       raise ETooMuchIterations.Create('Превышено максимальное количество итераций ('+inttostr(FMaxIterations)+')!');

     inc(N);

     x1:=Phi(x0);

     DrawStep(x1);

     if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(x1);

     end;

     if Assigned(FOnNextStep) then

       FOnNextStep(x1);

    until ((x1-x0)<FEpsilon);

    Result:=x1;

 end;

 function TEquation.Calculate_Newton: Double;

 var N: integer;

     x0, x1, d: double;

 begin

   N:=1;

   x1:=FMin;

   if F(FMax)*SecondDerivative(FMax)>0 then

     x1:=FMax;

   DrawStep2(x1);

   if Assigned(FOnNextStep) then

       FOnNextStep(x1);

   repeat

     if N>FMaxIterations then

       raise ETooMuchIterations.Create('Превышено максимальное количество итераций ('+inttostr(FMaxIterations)+')!');

     x0:=x1;

     if FirstDerivative(X0)=0 then

       raise EZeroDerivatite.Create('На шаге '+inttostr(N)+' производная стала равна нулю!');

     x1:=x0-(F(x0)/FirstDerivative(X0));

     DrawStep2(x1);

     inc(N);

     if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(x1);

     end;

     if Assigned(FOnNextStep) then

       FOnNextStep(x1);

     if abs(x1)>1 then

       d:=(x1-x0)/x1

     else

       d:=x1-x0;

   until ((d<=FEpsilon) and (abs(F(x1))<=100*Fepsilon));

   Result:=x1;

   if Assigned(FChart) then

     begin

         FChart.Series[0].Title:='Функция ('+inttostr(N)+' итераций).';

         FChart.Series[1].Title:='X='+FloatToStr(Result);

     end;

 end;

 procedure TEquation.DrawStep(x: Double);

 begin

   if Assigned(FChart) then

     FChart.Series[1].AddXY(x, F(x));

 end;

 procedure TEquation.DrawStep2(x: Double);

 begin

   if Assigned(FChart) then

   begin

     if ((F(x)<0) and (FirstDerivative(x)>0)) then

     begin

       FChart.Series[1].AddXY(x, F(x));

       FChart.Series[2].AddXY(x, 0);

       FChart.Series[2].AddXY(x, F(x));

     end

     else

     begin

       FChart.Series[1].AddXY(x, F(x));

       FChart.Series[2].AddXY(x, F(x));

       FChart.Series[2].AddXY(x, 0);

     end

   end;

 end;

function TEquation.F(x: Double): Double;

begin

 case FEquation of

   1: Result:=F2(x);

   2: Result:=F3(x);

   else Result:=F1(x);

 end;

end;

function TEquation.FirstDerivative(x: Double): Double;

begin

 case FEquation of

   1: Result:=FirstDerivative2(x);

   2: Result:=FirstDerivative3(x);

   else Result:=FirstDerivative1(x);

 end;

end;

function TEquation.Phi(x: Double): Double;

begin

 case FEquation of

   1: Result:=Phi2(x);

   2: Result:=Phi3(x);

   else Result:=Phi1(x);

 end;

end;

function TEquation.SecondDerivative(x: Double): Double;

begin

 case FEquation of

   1: Result:=SecondDerivative2(x);

   2: Result:=SecondDerivative3(x);

   else Result:=SecondDerivative1(x);

 end;

end;

procedure TEquation.SetNewEquation(AEquation: integer; AMin, AMax,

 AEpsilon: double; AMethod: integer);

begin

   FEquation:=AEquation;

   FMin:=AMin;

   FMax:=AMax;

   FEpsilon:=AEpsilon;

   FMethod:=AMethod;

   DrawF;

end;

function TEquation.GetMin: Double;

begin

 Result:=FMin;

end;

procedure TEquation.SetMin(const Value: Double);

begin

 FMin:=Value;

end;

function TEquation.GetChart: TChart;

begin

 Result:=FChart;

end;

function TEquation.GetEpsilon: Double;

begin

 Result:=FEpsilon;

end;

function TEquation.GetMax: Double;

begin

 Result:=FMax;

end;

function TEquation.GetMethod: integer;

begin

 Result:=FMethod;

end;

function TEquation.GetOnNextStep: TNextStepEvent;

begin

 Result:=FOnNextStep;

end;

function TEquation.GetResult: Double;

begin

 Result:=FResult;

end;

procedure TEquation.SetChart(const Value: TChart);

begin

 FChart:=Value;

end;

procedure TEquation.SetMax(const Value: Double);

begin

 FMax:=Value;

end;

procedure TEquation.SetMethod(const Value: integer);

begin

 FMethod:=Value;

end;

procedure TEquation.SetOnNextStep(const Value: TNextStepEvent);

begin

 FOnNextStep:=Value;

end;

initialization

 TComObjectFactory.Create(ComServer, TEquation, Class_Equation,

   'TEquation', '', ciMultiInstance, tmApartment);

end.

Результаты работы программы:

 

 

 

Выводы: таким образом, мы изучили способы работы с компонентами COM. Мы научились создавать COM-сервер и COM-клиент.


 

А также другие работы, которые могут Вас заинтересовать

10017. Основы редактирования документов в MS Word 180.5 KB
  Основы редактирования документов в MS Word Цель: Освоить правила редактирования текста: выделение перенос копирование удаление фрагментов текста. Рекомендации к выполнению Редактирование внесение изменений в набранный текст. Чаще всего приходится стирать ошибо
10022. Инновационные технологии в проектировании нового туристического продукта 509.4 KB
  Инновационные технологии в проектировании нового туристического продукта Введение Актуальность дипломного исследования. Прошедший ХХ век наряду со многими феноменальными событиями и явлениями в жизни мирового сообщества продемонстрировал чуть ли не взрывной ха...
10023. Моделирование кривых титрования с помощью MathCad 49.5 KB
  Моделирование кривых титрования с помощью MathCad. Рассматривается пример построения кривой титрования в Mathcad. Постановка задачи и порядок выполнения работы описывается в соответствующей обучающей программе. Студенты должны запустить Mathcad и обучающую программу Титрова...