Переменная времени
Delphi 1
Используйте переменную типа TDateTime.
procedure TForm1.XXXXXXXClick(Sender: TObject);
var StartTime, EndTime, ElapsedTime :TDateTime;
begin
StartTime := Now;
{Здесь поместите свой код}
EndTime := Now;
ElapsedTime := EndTime - StartTime;
Label1.Caption := TimeToStr(ElapsedTime);
end;
{теперь все это в памяти, но в нашем случае это хорошее место. }
var
before,after,elapsed : TDateTime;
Ehour, Emin, Esec, Emsec : WORD;
…
before := now;
some_process();
after := now;
elapsed := after - before;
decodetime(elapsed, Ehour, Emin, Esec, Emsec);
теперь Ehour:Emin:Esec.Emsec будет содержать истекшее время.
Это то, что я хотел. fStartWhen содержит дату/время начала процесса. (fStartWhen := NOW). OneSecond — константа, определенная как 1/24/3600. (Да, эта программа может выполняться для нескольких дней. Но даже самый быстрый P5 может не справиться с большим количеством данных!)
PROCEDURE TformDBLoad.UpdateTime;
VAR Delta: TDateTime
BEGIN
fLastUpdate := NOW
IF ABS(fStartWhen - fLastUpdate ) < OneSecond THEN EXIT
Delta := fLastUpdate - fStartWhendoElapsedTime.Caption := FORMAT('%1. дней из %s', [INT(Delta),FORMATDATETIME('hh:nn:ss', FRAC(Delta))])
END;
Математика
Как научить Delphi делать правильное округление дробных чисел?
Nomadic советует:
Целая коллекция способов -
Для решения этой проблемы мною написана функция, которую можно модифицировать для всех случаев. Смысл заключается в том, что рассматривается строка. После этого все проблемы с округлением снялись.
Function RoundStr(Zn:Real;kol_zn:Integer):Real;
{Zn-значение; Kol_Zn-Кол-во знаков после запятой}
Var
snl,s,s0,s1,s2:String;
n,n1:Real;
nn,i:Integer;
begin
s:=FloatToStr(Zn);
if (Pos(',',s)>0) and (Zn>0) and (Length(Copy(s,Pos(',',s)+1,length(s)))>kol_zn) then begin
s0 := Copy(s,1,Pos(',',s)+kol_zn-1);
s1 := Copy(s,1,Pos(',',s)+kol_zn+2);
s2 := Copy(s1,Pos(',',s1)+kol_zn,Length(s1));
n := StrToInt(s2)/100;nn := Round(n);
if nn >= 10 then begin
snl := '0,';
For i := 1 to kol_zn - 1 do snl := snl + '0';
snl := snl+'1';
n1 := StrToFloat(Copy(s,1,Pos(',',s)+kol_zn))+StrToFloat(snl);
s := FloatToStr(n1);
if Pos(',',s) > 0 then s1 := Copy(s,1,Pos(',',s)+kol_zn);
end else s1 := s0 + IntToStr(nn);
if s1[Length(s1)]=',' then s1 := s1 + '0';
Result := StrToFloat(s1);
end else Result := Zn;
end;
Все-таки работа со строками здесь излишество -
function RoundEx( X: Double; Precision : Integer ): Double;
{Precision : 1 - до целых, 10 - до десятых, 100 - до сотых...}
var
ScaledFractPart, Temp : Double;
begin
ScaledFractPart := Frac(X)*Precision;
Temp := Frac(ScaledFractPart);
ScaledFractPart := Int(ScaledFractPart);
if Temp >= 0.5 then ScaledFractPart := ScaledFractPart + 1;
if Temp <= -0.5 then ScaledFractPart := ScaledFractPart - 1;
RoundEx := Int(X) + ScaledFractPart/Precision;
end;
Разное
Генерация еженедельных списков задач
Мне необходима программа, которая генерировала бы еженедельные списки задач. Программа должна просто показывать количество недель в списке задач и организовывать мероприятия, не совпадающие по времени. В моем текущем планировщике у меня имеется 12 групп и планы на 11 недель.
Мне нужен простой алгоритм, чтобы решить эту проблему. Какие идеи?
Вот рабочий код (но вы должны просто понять алгоритм работы):
unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private { Private declarations }
public { Public declarations }
end;
var Form1: TForm1;
implementation
{$R *.DFM}
const maxTeams = 100;
var
Teams: Array[1..maxTeams] of integer;
nTeams, ix, week, savix: integer;
function WriteBox(week: integer): string;
var
str: string;
ix: integer;
begin
Result := Format('Неделя=%d ',[week]);
for ix := 1 to nTeams do begin
if odd(ix) then Result := Result+' '
else Result := Result+'v';
Result := Result+IntToStr(Teams[ix]);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
nTeams := StrToInt(Edit1.Text);
if Odd(nTeams) then inc(nTeams); {должны иметь номера каждой группы}
ListBox1.Clear;
for ix := 1 to nTeams do Teams[ix] := ix;
ListBox1.Items.Add(WriteBox(1));
for week := 2 to nTeams-1 do begin
Teams[1] := Teams[nTeams-1]; {используем Teams[1] в качестве временного хранилища}
for ix := nTeams downto 2 do if not Odd(ix) then begin
savix := Teams[ix];
Teams[ix] := Teams[1];
Teams[1] := savix;
end;
for ix := 3 to nTeams-1 do if Odd(ix) then begin
savix := Teams[ix];
Teams[ix] := Teams[1];
Teams[1] := savix;
end;
Teams[1] := 1; {восстанавливаем известное значение}