1.1 Постановка задачи.
Предлагается написать программу для измерения времени исполнения типовой задачи (сортировки массива, поиск минимума, максимума и т.п.) с точностью до 1 мкс.
Вариант задания:
10 | Вычисление интеграла методом трапеций с точностью до eps | e=0.01, 0.001, 0.00001 |
1.2 Решение
1.2.1 Интерфейс пользователя
1.1.2.2 Текст программы
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
intfunc in 'intfunc.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'Задача 4.2';
Application.CreateForm(TForm1, Form1);
Application.Run;
end.unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Mask, AdvSpin, Math;
type
TForm1 = class(TForm)
Memo1: TMemo;
GroupBox1: TGroupBox;
Eps_set: TAdvSpinEdit;
Label1: TLabel;
Label2: TLabel;
Result_Field: TEdit;
Run_Test: TButton;
Times_result: TEdit;
Label3: TLabel;
Label4: TLabel;
CPU_Speed: TEdit;
procedure Run_TestClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses intfunc;
{$R *.dfm}
function RDTSC:comp;
var
TimeStamp:record
case byte of
1: (Whole:comp);
2: (Lo,Hi: LongInt);
end;
begin
asm
db $0F, $31
mov [TimeStamp.lo],eax
mov [TimeStamp.Hi],edx
end;
result:= TimeStamp.Whole;
end;
function GetFrequence : longword;
var
Time_Lo, Time_Hi: comp;
begin
Sleep(1);
Time_Lo:= RDTSC;
Sleep(1000);
Time_Hi:= RDTSC;
result:= Round((Time_Hi-Time_lo));
end;
function intSin(x: Double): Double;
begin
Result := sin(x);
end;
procedure TForm1.Run_TestClick(Sender: TObject);
var Time_Lo, Time_Hi: comp;
Freq : longword;
begin
if(Eps_set.FloatValue=0) then exit;
Freq:=GetFrequence;
CPU_Speed.Text:=FloatToStr(RoundTo(Freq/10E8,-2))+' ÃÃö';
Time_Lo:=RDTSC;
Result_Field.Text := FloatToStr(TrapezeInt(0, Pi, Eps_set.FloatValue, intSin));
Time_Hi:=RDTSC;
Times_result.Text:= FloatToStr((Time_Hi-Time_lo)/Freq)+' c';
end;
end.
{ ***Вычисление определенного интеграла методом трапеций с заданной точностью ***
Просто расчет площади под функцией, параметры: a,b - пределы интегрирования, a<=b
eps - допустимая погрешность, практически гарантируется, что расхождение результата
с истинным значением интеграла не превосходит по модулю указанную величину.
intF - подинтегральная функция. Естественно, желательно задавать функции,
интегрируемые в смысле Римана.
Примечание: Несобственные интегралы не считаем,
Проверок на переполнение нет...
**************************************************** }
unit intfunc;
interface
type
TIntFunc = function(X: Double): Double;
function TrapezeInt(a, b: Double; eps: Double; IntF: TIntFunc): Double;
implementation
function TrapezeInt(a, b: Double; eps: Double; IntF: TIntFunc): Double;
var
//S - площадь на предыдущей итерации,
//x - текущее значение аргумента
//base - высота трапеции
//n - число трапеций, удваивается на каждой итерации
S, x, base: Double;
i, n: Integer;
begin
//Сначала приближение одной трапецией
base := b - a;
Result := (IntF(a) + IntF(b)) / 2 * base;
eps := eps / 10; //Вообще говоря, величина делителя зависит от функции
n := 1;
repeat
S := Result;
base := base / 2;
n := n * 2;
//Новая площадь вычисляется на основе старой
Result := Result / 2;
//Ниже - просто вычисляем площади новых трапеций
for i := 1 to n div 2 do
begin
x := a + base * (i * 2 - 1);
Result := Result + IntF(x) * base;
end;
until abs(S - Result) <= eps;
end;
end.
1.2.3 Результаты отладки:
Как видим с увеличением требуемой точности подпрограмма выполняется все дольше.
0 коммент.:
Отправить комментарий