Autor Beitrag
rushifell
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mo 26.11.12 18:46 
Hallo,

ich habe eine Frage zu GetTickCount. Ich habe mal im Internet gelesen, man bräuchte bei GetTickCount eine Bereichsprüfung, da der Wert die Anzahl der Millisekunden seit dem Systemstart zurückgibt und der Bereich nach etwa 50 Tagen überschritten wird. GetTickCount liefert einen Uint32-Wert zurück, also eine Variable vom Typ Cardinal.

Was passiert, wenn der höchste Wert, also 4294967295 überschritten wird? Die Zählung beginnt von vorne!? Nun habe ich folgendes ausprobiert:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.Button1Click(Sender: TObject);
Var c1, c2:cardinal;
begin
 c1:=4294967295//Höchster Cardinal-Wert
 c2:=10;
ShowMessage(InttoStr(c2-c1)); //liefert den Wert 11
end;

Der Wert 11 wird (schätze ich mal) zurückgeliefert, da die Zählung bei 0 beginnt (0..10 sind 11 Ziffern). Es wird also, wie ich erwartet hätte, ein negativer Wert zurückgeliefert. Die Differenz stimmt bis aus die kleine Abweichung von einer Millisekunde.

Nun habe ich für die Zeitmessung folgenden Code geschrieben. Leider kann ich es aus Zeitgründen nicht testen ;-) Aber eigentlich müsste das doch funktionieren. Oder habe ich etwas übersehen?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
type

TClock=record
 OldTick,NewTick,
 MilliSeconds,
 TimeElapsed:Cardinal;
end;
...
implementation
Var Clock:TClock;
...
//Zeitmessung starten:
procedure TForm1.Button2Click(Sender: TObject);
begin
 Clock.OldTick:=GetTickCount;
 Clock.TimeElapsed:=0;        //Verstrichene Zeit auf 0 setzen
 Timer1.Enabled:=True;        //Timer starten
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Clock.NewTick:=GetTickCount;

//verstrichene Zeit seit der letzten Messung:
 Clock.Milliseconds:=Clock.NewTick-Clock.OldTick; //Differenz
 Clock.TimeElapsed:=Clock.TimeElapsed+Clock.MilliSeconds;
 Clock.OldTick:=Clock.NewTick;
 Form1.Caption:=IntToStr(Clock.TimeElapsed); //Verstrichene Zeit in Millisekunden
end;

Selbst wenn die Zeit um 1 Millisekunde abweicht, könnte ich damit gut leben.

Viele Grüße
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mo 26.11.12 19:16 
Der Cardinal läuft bein hochzählen ebenso über wie bei Rechenoperationen, das ganze ist sauber.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
Function Cardinal2Bin(c:Cardinal):String;
var
  I: Integer;
begin
    SetLength(Result,32);
    for I := 0 to 31 do
      begin
        Result[32-i] := IntToStr(Integer(c and 1))[1];
        c := c shr 1;
      end;
end;

procedure TForm3.Button1Click(Sender: TObject);
var
 c,d:Cardinal;
 i:Integer;
begin
  c := 4294967294;
  d := c;
  for I := 0 to 4 do
      begin
        memo1.Lines.Add(Cardinal2Bin(c));
        inc(c);
        memo1.Lines.Add('Diff:' + IntToStr(c-d));
        d := c;
      end;
end;

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS

Für diesen Beitrag haben gedankt: rushifell
rushifell Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mo 26.11.12 19:34 
Danke bummi. Also stimmt die Zeitmessung, wie ich sie durchführe, und es gibt auch keine Abweichung von einer Millisekunde. :D

Hat jemand eine Ahnung, ob es mit dem QueryPerformanceCounter Probleme geben kann. Oder soll ich dafür ein neues Topic erstellen?
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mo 26.11.12 19:42 

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Mo 26.11.12 20:23 
Warum in die Ferne schweifen? www.entwickler-ecke....iewtopic.php?t=89302
rushifell Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mo 26.11.12 20:28 
Danke, wie man den QueryPerformanceCounter verwendet, weiss ich. Meine Frage ist, ob es notwendig ist zu prüfen, ob die Differenz zwischen Startwert und Endwert negativ bzw. größer 0 ist? Schließlich wird hier ein LARGE_INTEGER zurückgeliefert, also 64 Bit signed.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Var OldVal, NewVal, Frequency:Int64;
    TimeFactor:Single;
Begin
 QueryPerformanceCounter(OldVal);
 ...
 QueryPerformanceCounter(NewVal);
 QueryPerformanceFrequency(Frequency);
 IF NewVal-OldVal>0 then
    TimeFactor := ((NewVal-OldVal) /Frequency) else
    TimeFactor:=0

//TimeFactor * 1000 müsste dann die Zeit zwischen beiden
//Messungen in Millisekunden sein
End;


Es würde hier zwar ein Fehler in der Zeitmessung auftreten, wäre das Ergebnis jedoch negativ, wäre der Fehler wesentlich schlimmer.


Zuletzt bearbeitet von rushifell am Mo 26.11.12 20:53, insgesamt 1-mal bearbeitet
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Mo 26.11.12 20:38 
Hast Du Dir einmal ausgerechnet, wann der Counter (int64) bei einer Frequenz von 1 Millisekunde überläuft? Ich denke, sollte das jemals eintreten, tangiert Dich das nicht mehr.


Zuletzt bearbeitet von WasWeißDennIch am Di 27.11.12 09:09, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: rushifell
rushifell Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mo 26.11.12 20:47 
WasWeißDennIch hat folgendes geschrieben:
Hast Du Dir einmal ausgerechnet, wann der Counter (in64) bei einer Frequenz von 1 Millisekunde überläuft?

Naja, ich denke wenn QueryPerformanceCounter ebenfalls die Zeit seit dem Systemstart zurückliefert, dann wie bei GetTickCount etwas weniger als 50 Tage Laufzeit des Rechners.

Natürlich ist die Wahrscheinlichkeit, dass das in der Praxis eintritt recht gering, aber dennoch denkbar. Wenn ich einen Fehler durch eine einfache Zeile Code vermeiden kann, denke ich schon, dass meine Frage gerechtfertigt ist.

Ob das ganze 'ne Millisekunde oder nicht abweicht ist letztendlich natürlich egal. Bin eben Perfektionist :zwinker:
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mo 26.11.12 20:52 
Hallo,
user profile iconrushifell hat folgendes geschrieben Zum zitierten Posting springen:
ob es notwendig ist zu prüfen, ob die Differenz zwischen Startwert und Endwert negativ bzw. größer 0 ist?

Ich glaube eher nicht.
Bei 63-bit (ohne Vorzeichen) ist die größte Zahl 9223372036854775808. Bei einer Taktfrequenz von z.B. 4 GHz ergibt sich für die Variable Frequenz 4000000000 je Sekunde, d.h. rund 2,3 Milliarden Sekunden können bis zum Überlauf gezählt werden. Das sind über 70 Jahre und nicht nur 50 Tage.
Natürlich beginnt der Zähler nicht bei 0 und die Taktfrequenz ist wahrscheinlicher höher, aber am Prinzip ändert sich nichts.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein

Für diesen Beitrag haben gedankt: rushifell
rushifell Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mo 26.11.12 21:02 
Hoppla, grober Denkfehler meinerseits :oops:

Danke :beer: