Задача 50. Для проверки эффективности программ часто требуется определять и сравнивать время их работы. Создать модуль для поддержки таймера, включая процедуры задержки и определения времени, прошедшего с некоторого установленного момента.
Постараемся сделать решение независимым от особенностей операционной системы (т.е. воспользуемся процедурой получения текущего времени, а не счетчиком времени из области данных BIOS по адресу $40:$6C).
unit UTimeOut; {модуль поддержки таймера}
interface
Procedure SetTimeOut(TMilli:longint); {Установка счетчика таймера, TMilli - количество миллисекунд ("завели будильник")}
Function GetTimeOut:boolean; {Возвращает True, если с момента установки таймера прошло не менее чем TMilli миллисекунд ("будильник звенит")}
procedure SetTimer; {фиксирует счетчик таймера ("запустили секундомер")}
function GetTimer:longint; {возвращает количество миллисекунд, прошедших с момента фиксации счетчика }
procedure Wait(M:longint); {задержка на M миллисекунд}
Implementation
uses dos; {подключаем модуль Dos для доступа к процедуре получения текущего времени }
var Timer:longint;{момент фиксации таймера}
TTmilli:longint;{счетчик таймера}
{------------функция ConvertTime -------------}
function ConvertTime(H,M,S,Milli:integer):longint;
begin {функция переводит часы, минуты, секунды и миллисекунды в миллисекунды}
ConvertTime:= longint*0360000+longint(M)*0006000+
longint(s)*0000100+longint(Milli);
end;
{------------функция GetCurrentTime -------------}
function GetCurrentTime:longint;{возвращает текущее время в миллисекундах}
var h,m,s,milli:word;
begin
GetTime(h,m,s,milli);{вызов процедуры из модуля Dos для получения текущего времени}
GetCurrentTime:=ConvertTime(h,m,s,milli);
end;
{------------процедура Wait -------------}
procedure Wait(M:longint);
begin
SetTimeOut(M);{устанавливаем счетчик}
while not GetTimeOut do;{ожидаем "звонка"}
end;
{------------процедура SetTimer -------------}
Procedure SetTimer;
begin Timer:=GetCurrentTime; end;
{------------функция GetTimer -------------}
function GetTimer:longint;
var NewTime:longint;
begin
NewTime:=GetCurrentTime;{получаем текущее время}
{Рассчитываем количество прошедших миллисекунд с момента фиксации таймера. Учитываем возможность перехода за полночь.}
if newTime>=Timer then Gettimer:=Newtime-Timer
else Gettimer:=Newtime-Timer+8640000;
end;
{------------процедура SetTimeOut -------------}
Procedure SetTimeOut(TMilli:longint);
begin TTMilli:=TMilli; SetTimer end;
{------------функция GetTimeOut -------------}
Function GetTimeOut:boolean;
begin
{возвращаем True, если количество времени, прошедшего с момента фиксации таймера, превышает значение счетчика}
if TTMilli<GetTimer then GetTimeOut:=true
else GetTimeOut:=false;
end;
end. {модуль завершен}
Для проверки действия процедур и функций модуля создадим несколько программ.
Задача 51. Сравнить скорость работы циклов For, While и Repeat.
Решение:
uses crt,uTimeOut;
var i:longint;
begin
clrscr;
write('Время работы цикла For ');
Settimer;
for i:=1 to 100000000 do;
writeln(getTimer,' миллисекунд');
write('Время работы цикла While ');
Settimer;
i:=1; while i<=100000000 do inc(i);
writeln(getTimer,' миллисекунд');
write('Время работы цикла Repeat ');
Settimer;
i:=1; repeat inc(i) until i>100000000;
writeln(getTimer,' миллисекунд');
readln;
end.
В результате выполнения данной программы (компьютер с процессором Pentium-120) на экране появятся три строки:
Время работы цикла For 769 миллисекунд
Время работы цикла While 852 миллисекунд
Время работы цикла Repeat 856 миллисекунд
На самом деле, при каждом запуске программы мы получим чуть отличные результаты, однако общая тенденция достаточно ясна.
Задача 52. Создайте программу, с помощью которой покажите, насколько сильно замерз главный герой одного из стихотворений Некрасова.
Решение проанализируйте сами:
uses crt,uTimeOut;
const TOut:real=1;
s:string='Однажды в студ-д-д-д-еную зимнюю пору '+
'я из-з-з лес-с-су в-в-в-вышел ...';
var i:integer;
begin
clrscr;
for i:=1 to length(s) do begin
write(s[i]);
wait(round(TOut));
TOut:=TOut*1.05;
end;
readln;
end.