Ну и не надо! Мы ведь не чайники? Конечно, не чайники! Сами напишем. При написании программ последовательный код стараются обединить в цыклы. Код, повторяющийся в програме выносят в отдельные процедуры и функции. А код, который явно будет использоватся не в одной программе, выносят в модули. Мы так и сделаем. Давайте создадим в Паскале файл timer.pas и начнем. Как известно название модуля и файла должны совпадать, поетому пишем:
unit timer;
Далее необходимо создать интерфейсную часть модуля. Тут давайте остановимся и разберемся что нам нужно. Во-первых нам нужны средства для измерения времени исполнения кода. Во-вторых средства по остановке программы на определенное время. Кроме того, при остановке может, понадобится вывод времени, которое прошло.
interface
procedure start (var t:longint);
procedure stop (var t:longint);
procedure pause (t:longint; show:boolean);
Итак, мы обявили три процедуры. Процедуры start и stop будут служить для измерения времени выполнения кода, а pause станет заменой delay. Переменная t - будит служить для передачи данных о времени. show - для разрешения или запрещения вывода времени на екран. Далее следует исполнительная часть. Она служит для обявления локальных констант, переменных и типов. В данном модуле они нам не нужны:
implementation
Далее следует самое интересное. Вы еще не задумывались каким же способом мы будем производить замер времени? А почему бы не использавать аппаратный таймер? Темболее это очень просто:
systemtimer:longint absolute $0040:$006c;
Вот и все! Нет, модуль не весь, но мы имеем полный доступ к аапаратному таймеру, расположеному по физическому адресу $0040:$006c. Значение двойного слова по этому адресу увеличивается на единицу 18.2 раза в секунду и независит от производительности системы. Нам осталось только написать примитивные процедуры для оперирования с таймером:
procedure start (var t:longint);
begin
t:=systemtimer;
end;
procedure stop (var t:longint);
begin
t:=systemtimer-t;
end;
procedure pause (t:longint; show:boolean);
var xn,xt:longint;
begin
xt:=0;
xn:=systemtimer;
while ((xt-xn)/18.2)*1000 < t do
begin
xt:=systemtimer;
if show then
writeln((xt-xn)/18.2:6:4)
end;
end;
Ну, и долгожданный
end.
Все, компилируем. Хочется сразу проверить работу, не так ли?
program timerprimer;
uses timer;
var i : integer;
a :real;
time : longint;
begin
randomize;
start(time);
for i:=1 to 30000 do
a:=sin(sqrt(i))*cos(sqrt(random(10000)));
stop(time);
writeln('Время выполнения: ',time/18.2:6:4);
readln;
pause(10000, true);
end.
Данная программа демонстрирует возможности модутя timer. В начале она исполняет цыкл от 1 до 30000 в котором высчитывает значение а. Время выполнения этого цыкла и замеряют наши процедуры start и stop. После чего, дождавшись нажатия на enter делаем паузу на 10.000 секунд с разрешаем процедуре pause осуществлять вывод на екран.
Теперь вы сможете использовать точный таймер в своих программах. А почему же я не воспользовался процедурой gettime? Только из-за ее громоздкости? Конечно нет. Посмотрите на код. Что мы собственно использовали? Только прямой доступ к физическому адресу аппаратного таймера. Так кто мешает использовать его в других языках программирования? Вот тут то и оно.