Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Delphi extrem falsche rundung


IhopeonlyReader - Di 09.04.13 14:57
Titel: Delphi extrem falsche rundung
Guten Tag,
ich habe mal eine Frage:

Delphi-Quelltext
1:
FloatToStr( ( 1/((Now-NL)*24*60*60) )); //(Now und NL sind vom Typ TDateTime)                    

(Now-NL)*86400 ist = die Differenz in Sekunden...
1/DifferenzInSekunden = wie oft es in der sekunde ausgeführt wurde..
soweit alles ok :)

allerdings:

Delphi-Quelltext
1:
2:
3:
FloatToStr( ( 1/((Now-NL)*24*60*60) )); //liefert korrekt 9,1762...
FloatToStr(Round ( 1/((Now-NL)*24*60*60) ); //liefert 91
IntToStr(Round ( 1/((Now-NL)*24*60*60) ); //liefert 91

da ich mich sehr über ein solchen Rundungsfehler wunderte, programmierte ich selber eine Rundungsfunktion

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Function Runden(Zahl: Extended): Integer;
  var Ganzzahl: Integer;
      PosNeg: Integer;
  begin
  if Zahl>0 then PosNeg := 1 else PosNeg := -1;
  Ganzzahl := Trunc(Zahl);
  if Frac(Zahl)>=0.5 then Result := Ganzzahl+(1*PosNeg) else Result := Ganzzahl;
  end;

jedoch:

Delphi-Quelltext
1:
2:
FloatToStr(Runden( 1/((Now-NL)*24*60*60) ); //liefert 91
IntToStr(Runden( 1/((Now-NL)*24*60*60) ); //liefert 91


ein weiteres Wunder... darauf:

Delphi-Quelltext
1:
FloatToStr(Trunc( 1/((Now-NL)*24*60*60) ); //liefert 91                    


jetzt meine Frage: wieso wird aus 9.1 bei jeglicher rundungsart 91? wenn ich direkt Round(9.16746474946846...) schreibe, so ist das Ergebnis korrekt

Moderiert von user profile iconNarses: Beiträge zusammengefasst

Edit: Auch

Delphi-Quelltext
1:
2:
3:
4:
5:
var C: Extended;
begin
C := 1/((Now-NL)*24*60*60);
IntToStr( Runden( C ) ); //liefert 91
end;


WasWeißDennIch - Di 09.04.13 15:14

Und wenn Du testhalber einmal SecondsBetween aus DateUtils verwendest?


Tranx - Di 09.04.13 15:31

Also, bei Delphi 5 wird so gerundet, wie zu erwarten ist. Keine falschen Ergebnisse (9,17 wird zu 9 gerundet). Allerdings habe ich now in eine zweite Variable NL2 gespeichert und nicht now - NL sondern NL2 - NL gerechnet.

P.S.: Auch bei Verwendung von now keine anderen Ergebnisse.


Mathematiker - Di 09.04.13 15:31

Hallo,
außer dass

Delphi-Quelltext
1:
2:
FloatToStr(Round ( 1/((Now-NL)*24*60*60) ); //liefert 91
IntToStr(Round ( 1/((Now-NL)*24*60*60) ); //liefert 91

nicht stimmen können (schließende Klammern fehlen), habe ich Deine Routinen getestet:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var nl:tdatetime;
begin
     nl:=now-1/9.1762/86400;
     memo1.lines.add(FloatToStr( ( 1/((Now-NL)*24*60*60) ))); //liefert korrekt 9,1762...
     memo1.lines.add(FloatToStr(Round ( 1/((Now-NL)*24*60*60)))); //liefert 9 !!!!
     memo1.lines.add(IntToStr(Round ( 1/((Now-NL)*24*60*60)))); //liefert 8  !!!!
     memo1.lines.add(floattostr(1/9.1762/86400));
end;

liefern die Rundungen korrekte(!) Werte.
Die letzte Zeile habe ich aufgenommen, um zu sehen, welcher Zeitraum eigentlich gemessen wird. Es sind 0,109 s.
Also bei mir funktioniert es ohne Probleme.
Du müsstest wahrscheinlich mehr Quelltext zeigen, um den eigentlichen Fehler zu lokalisieren.

Beste Grüße
Mathematiker


IhopeonlyReader - Di 09.04.13 15:33

FloatToStr( Round( 1000/MilliSecondsBetween(NL,Now) ))
Muss es dann sein, da es ca 0.1 sec liefert SecondsBetween 0 aus...
Aus dem oben genannten befehl kommt sogar 901 raus


WasWeißDennIch - Di 09.04.13 15:42

Was genau willst Du denn eigentlich berechnen?


IhopeonlyReader - Di 09.04.13 15:43


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:
30:
31:
32:
33:
34:
35:
36:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  NL: TDateTime;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
var T: String;
begin
   T := 'FpS: '+ FloatToStr( Round( 1/((Now-NL)*24*60*60) )); ;
   NL := Now;
   Canvas.TextOut(0, ClientHeight- Canvas.TextHeight(T), T);
   //weitere befehle
end;

end.


Moderiert von user profile iconNarses: Beiträge zusammengefasst

user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
Was genau willst Du denn eigentlich berechnen?

FpS


Mathematiker - Di 09.04.13 15:48

Hallo,
unter http://www.delphipraxis.net/115759-exakte-fps.html findest Du einen Vorschlag mittels QueryPerformanceCounter, der relativ genau ist.

Beste Grüße
Mathematiker


WasWeißDennIch - Di 09.04.13 15:48

Die bekommst Du doch mit einem Timer gar nicht heraus. Wenn, dann müsstest Du irgendwie z.B. 1000 Frames zeichnen und die dafür benötigte Zeit messen oder andersherum eine definierte Zeit lang so schnell wie möglich Frames zeichnen und diese zählen. Daraus ließen sich dann die FpS ermitteln.


IhopeonlyReader - Di 09.04.13 15:53

user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
Die bekommst Du doch mit einem Timer gar nicht heraus.

Ich mache das so:
Startbutton: - DateTime abspeichern ( NL )
- Timer anmachen

im Timer:
- Text:= FloatToStr( Round( 1/((Now-NL)*24*60*60) ));
- NL := Now;
- zeichnen
- canvas.textout

Edit: FpS ist vielleicht nicht ganz korrekt.. sondern die Zeichnungen pro Sekunde


WasWeißDennIch - Di 09.04.13 16:01

Dazu müsstest Du die Zeichnungen aber auch zählen, sonst fehlen Dir doch die Berechnungsgrundlagen.


IhopeonlyReader - Di 09.04.13 16:03

Es geht darum, anzuzeigen, wieviele Zeichnungen in der Sek geschafft werden würden, wenn sie in der Geschwindigkeit (Zeit) gezeichnet werden, wie das letzte


WasWeißDennIch - Di 09.04.13 16:06

Und wie soll Dir ein Timer da weiterhelfen? Sofern ich den Code richtig überblicke, würde eine Änderung des Timer-Intervalls signifikant andere Ergebnisse liefern.


Mathematiker - Di 09.04.13 16:13

Hallo,
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Es geht darum, anzuzeigen, wieviele Zeichnungen in der Sek geschafft werden würden, wenn sie in der Geschwindigkeit (Zeit) gezeichnet werden, wie das letzte

Mein Vorschlag:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var Time1, Time2, Freq: Int64;
    wert : extended;
begin
    QueryPerformanceFrequency(Freq);
    QueryPerformanceCounter(Time1);

    //hier Deine Zeichnung

    QueryPerformanceCounter(Time2);
    wert:=1000*(Time2-Time1)/freq;
    label1.caption:=floattostrf(wert,ffgeneral,4,3)+' ms';
    label2.caption:=floattostrf(1000/wert,ffgeneral,4,3)+' Bilder je s';
end;


Beste Grüße
Mathematiker


IhopeonlyReader - Di 09.04.13 16:19

user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
Und wie soll Dir ein Timer da weiterhelfen? Sofern ich den Code richtig überblicke, würde eine Änderung des Timer-Intervalls signifikant andere Ergebnisse liefern.


Wenn das Timer Intervall auf 1 steht?
Ich benutte den Timer eigentlich nur um eine Whilescleife zu vermeiden (damit sich das Programm nicht aufhängt), und da es auf die zeit zwischen Zeichnung 1 und Zeichnung 2 ankommt und das interval nun einmal dazwischen liegt, muss dies mitdrin sein
komischerweise:
T := 'FpS: '+ S + ' | '+Copy(S, 0, Pos(',', S)-1); // FpS: 9.0909 | 91
// oder manchmal auch: FpS: 9.909090| 910


FinnO - Di 09.04.13 16:26

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:

Wenn das Timer Intervall auf 1 steht?
Ich benutte den Timer eigentlich nur um eine Whilescleife zu vermeiden (damit sich das Programm nicht aufhängt)[...]


Moin,

genau das ist kein sinnvoller Ansatz. Wenn du Code so oft wie möglich ausführen willst, musst du schon eine (Endlos)schleife benutzen. Damit sich dein Programm nicht "aufhängte" empfehle ich:


Delphi-Quelltext
1:
2:
3:
4:
5:
while(true)
begin
  doSth();
  Application.ProcessMessages();
end;


WasWeißDennIch - Di 09.04.13 16:28

Ein Timer-Interval von 1 kannst Du vergessen, nach meinem Kenntnisstand müsste das Minimum bei ca. 50 liegen. Außerdem ist ein Timer relativ ungenau, da er keine hohe Priorität hat. Wenn Dein Programm nicht blockieren soll, kommst Du m.M.n. mittelfristig nicht um einen Thread herum.


IhopeonlyReader - Di 09.04.13 16:44

dennoch stimmt die "Rundung" nicht.. vorallem bei dem Versuch mit Copy müsste es doch klappen! das heißt, der Compiler schreibt mein code irgendwie um :(


Mathematiker - Di 09.04.13 16:49

Hallo,
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
dennoch stimmt die "Rundung" nicht..

Nein!!! Die Rundung stimmt (siehe weiter oben)! Derartige Fehler macht Delphi nicht.
Das Problem ist der Timer.
Da Du offensichtlich meine Beiträge ignorierst, klinke ich mich hier aus. :evil:

Beste Grüße
Mathematiker


WasWeißDennIch - Di 09.04.13 16:50

Das glaub ich kaum. Speicher doch zunächst Now() einmal in einer Variablen zwischen und benutz dann die zur Berechnung. Dann schreibe Dir eine Funktion für die Ermittlung der Sekunden und benutze diese. Deren Ergebnis wird dann gerundet. Wenn dabei unterschiedliche Ergebnisse herauskommen, dann stimmt etwas mit Deinem Delphi nicht, aber das steht IMO eher nicht zu erwarten.


IhopeonlyReader - Di 09.04.13 17:00

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:

Da Du offensichtlich meine Beiträge ignorierst, klinke ich mich hier aus. :evil:

Beste Grüße
Mathematiker


du versucht mich "umzuprogrammieren" nicht die Frage zu beantworten !
Ich möchte den Quelltext nicht ändern, sondern wissen warum die Rundung nicht stimmt... sonst müsste
Copy(T, 0, Pos(',', T)-1) bei T='3,161' eigentlich 3 ergeben und nicht 300 !


Mathematiker - Di 09.04.13 17:11

Hallo,
also ich habe noch einmal

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Timer1Timer(Sender: TObject);
var T: String;
begin
   T := FloatToStr( ((Now-NL)*24*60*60) ); 
   memo1.lines.add(T);
   T := 'FpS: '+ FloatToStr( 1/((Now-NL)*24*60*60) );
   memo1.lines.add(T);
   T := 'FpS: '+ FloatToStr( Round( 1/((Now-NL)*24*60*60) ));
   memo1.lines.add(T);
   NL := Now;
   timer1.enabled:=false;
   //weitere befehle
end;

mit einem Timerinterval = 1 und dem Start mit einem Buttonclick getestet. Ich erhalte auf meiner alten Mühle

Quelltext
1:
2:
3:
0,0160002149641514
FpS: 62,4991603075651
FpS: 62

und immer wieder ähnliche Werte, d.h., es wird vollkommen richtig gerundet. Hast Du nach der Anzeige den Timer deaktiviert?

Beste Grüße
Mathematiker


Tranx - Di 09.04.13 17:13

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
dennoch stimmt die "Rundung" nicht..

Nein!!! Die Rundung stimmt (siehe weiter oben)! Derartige Fehler macht Delphi nicht.
Das Problem ist der Timer.


Ich kann Steffen nur zustimmen, die Rundung ist nicht das Problem. Ohne Timer habe ich korrekte Werte erhalten. Möglicherweise funkt Dir der Timer dazwischen. Ich würde den rausnehmen und die Zeitmessung in einer Endlosschleife wie folgt programmieren:


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:
interface

var
  PROCABBRUCH : boolean = FALSE;
implementation


procedure Form1.Btn1Click(Sender : TObject);
begin
  PROCABBRUCH := true;  
end;
:
:

//Prozedur zur Zeitmessung:

  ok := TRUE;
  While ok do
  begin
    Application.ProcessMessages;
    if PROCABBRUCH then Exit;
    (Zeitmessungsroutine);
  end;


Du benötigst einen Button (btn1 oder anders bezeichnet) Dieser erhält die ONClick-Prozedur wie oben. Bei jedem Schleifendurchgang wird die Prozedur Application.Processmessages durchlaufen, also wenn Du auf den Button drückst, wird in der OnClick-Prozedur die globale Variable PROCABBRUCH auf true gesetzt udn dann bei der Abbfrage logischerweise die Endlosschleife mit Exit abgebrochen.


IhopeonlyReader - Di 09.04.13 17:35

Um zu zeigen, dass nicht die ProgrammierART sondern Delphi einen Felder macht folgendes:
T := 'FpS: '+ FloatToStr( ( 1 / ((Now-NL)*24*60*60) )); //= 9.1
T := 'FpS: '+ FloatToStr( Round( 1 / ((Now-NL)*24*60*60) )); //= 91
T := 'FpS: '+ FloatToStr( Round( 1 / ((Now-NL)*24*60*60) )/1);//= 91
T := 'FpS: '+ FloatToStr( Round( 1 / ((Now-NL)*24*60*60) )/10); //=0.9

wenn round funktionieren würde, dann müsste wenn X/1 =91 x/10 =9.1 sein und nicht 0.9 !


WasWeißDennIch - Di 09.04.13 17:37

Wie sollen wir das nachvollziehen, wenn Du immer wieder auf now und nl zureifst, deren Werte wir nicht kennen?


IhopeonlyReader - Di 09.04.13 18:11

ich habe jetzt jede zeile für zeile "rausgenomen" (mit {}) und getestet, wann ein richtiges Ergebnis kam, und wann nicht..


Delphi-Quelltext
1:
2:
3:
4:
5:
    procedure DoIt;
    begin
    T := 'FpS: '+ FloatToStr( Round( 1/((Now-NL)*24*60*60) ));
    NL := Now;
    end;


Wunder:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
if FesteFpS then
  begin
  if TryStrToFloat(FpSRate.Text, C) then
      if ( (Now-NL)*24*60*60*C > 1 ) then 
        DoIt;
  end
else
  begin
  DoIt;
  end;

Hier kam 91 raus



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
if FesteFpS then
  begin
  if TryStrToFloat(FpSRate.Text, C) then
      if ( (Now-NL)*24*60*60*C > 1 ) then 
        DoIt;
  end
else
  begin
  //DoIt;
  end;

Hier kam 9 raus (richtige)

Das Ergebnis war immer falsch, wenn festeFpS True war und DoIt bei if not FresteFpS then ausgeführt wurde... bei False kam ein richtiges Ergebnis raus bzw. wenn vor dem 2ten DoIt ein //stand gab es keinen Fehler... wisst ihr warum?


Mathematiker - Di 09.04.13 18:16

Hallo,
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
wenn round funktionieren würde, dann müsste wenn X/1 =91 x/10 =9.1 sein und nicht 0.9 !

Also. Ich habe Deine Anweisungen im Timer(!) getestet. Ergebnis

Quelltext
1:
2:
3:
4:
   T := 'FpS: '+ FloatToStr( ( 1 / ((Now-NL)*24*60*60) )); //= FpS: 62,4991603075651
   T := 'FpS: '+ FloatToStr( Round( 1 / ((Now-NL)*24*60*60) )); //= 62
   T := 'FpS: '+ FloatToStr( Round( 1 / ((Now-NL)*24*60*60) )/1);//= 62
   T := 'FpS: '+ FloatToStr( Round( 1 / ((Now-NL)*24*60*60) )/10); //=6,2

D.h., es wird richtig gerundet.
Irgendwie habe ich den Eindruck, dass Dein Delphi "eine Meise" hat.

Beste Grüße
Mathematiker


IhopeonlyReader - Di 09.04.13 18:19

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:

Irgendwie habe ich den Eindruck, dass Dein Delphi "eine Meise" hat.

jap :D
wenn ich es so schreibe:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
if FesteFpS then
  begin
  if TryStrToFloat(FpSRate.Text, C) then
      if ( (Now-NL)*24*60*60*C > 1 ) then 
        DoIt;
  end
else
  begin
  DoIt;
  end;

und mit F9 kompiliere, zeigt er 91 an
ABER !!!!!!!!!!
kompiliere ich mit F8 und drücke dann zur Laufzeit F9, so zeigt er 9 (richtig!) an....


Boldar - Di 09.04.13 18:34

An dieser Stelle schlage ich vor, du zeigst mal komplette Quelltexte, sonst wird das hier nichts mehr. Am besten minimalisiert auf den Fehler.


WasWeißDennIch - Di 09.04.13 18:35

Das klingt nach irgend einem Seiteneffekt. Genaueres dazu kann man aber mangels Source nicht sagen.


IhopeonlyReader - Di 09.04.13 18:51

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
An dieser Stelle schlage ich vor, du zeigst mal komplette Quelltexte, sonst wird das hier nichts mehr. Am besten minimalisiert auf den Fehler.


Der Quelltext 3 Posts vor deinem ist alles.. alle andere hatte ich in {}... außer du willst noch sowas wie

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
//Den Quelltext hierzwischen stehen haben
end;



dann sähe das so aus:


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:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    FesteFpS: TCheckBox;
    FpSRate: TEdit;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  NL: TDateTime;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
var T: String;
    C: Extended;
  procedure DoIt;
    begin
    T := 'FpS: '+ FloatToStr( Round( 1/((Now-NL)*24*60*60) ));
    NL := Now;
    end;
begin
if FesteFpS.Checked then
  begin
  if TryStrToFloat(FpSRate.Text, C) then
      if ( (Now-NL)*24*60*60*C > 1 ) then 
        DoIt;
  end
else
  begin
  DoIt;
  end;
Canvas.TextOut(10, ClientHeight-Canvas.TextHeight(T), T);
end;

end.

Form besteht aus:
Timer1: TTimer; //Interval ist 1, er ist von anfang an Enabled := True
FesteFpS: TCheckBox;// Halt an und ausmachbar (von anfang an aus)
FpSRate: TEdit; //steht von anfang an 1 drin


Hierbei ensteht ein der Fehler... starte ich mit F8 und danach F9 funktioniert alles.. aber direkt F9 ist ein Fehler...
Wenn ich mit F8 zuerst gestartet habe, es dann klappt, dann Die Zahl im Edit größer als 70 wird, ist die angezeigte Zahl 66.. gehe ich nun wieder auf eine kleinere zahl z.B. 1, so wird die zahl 17 angezeigt.... (anstatt 1)


WasWeißDennIch - Di 09.04.13 19:15

Dann versuch doch erst einmal das, was ich vorher schon vorgeschlagen hatte (NOW ändert sich schließlich ständig):
Zitat:
Speicher doch zunächst Now() einmal in einer Variablen zwischen und benutz dann die zur Berechnung. Dann schreibe Dir eine Funktion für die Ermittlung der Sekunden und benutze diese. Deren Ergebnis wird dann gerundet.


Tranx - Di 09.04.13 19:47

Ich habe nun - bis auf die Prozedur TryStrToFloat, die ich durch einen Try .. except .. end-Konstrukt ersetzt habe, die Timerroutine geprüft. Es kommen bei mir keine Fehler beim Runden. 100,1 ergibt 100 und 50,56 ergibt 51.

Selbst wenn ich statt NL := now; schreibe: NL := now - 0.12/24/60/60, was ja bei der Differenz dann immer dazu führt, dass scheinbar eine Differenz von 0.12 Sekunden mindestens auftreten, wird korrekt gerundet (entwerder ist das Ergebnis 7 oder 8.

P.S. ich habe die Differenz NOW - NL und den ungerundeten Wert 1/((Now-NL)*86400) in T ausgegeben, und die gerundeten Werte stimmen immer!!!!

Ich weiß ehrlich nicht, wo der Fehler noch stecken soll.


Gerd Kayser - Di 09.04.13 20:20

user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
Ich weiß ehrlich nicht, wo der Fehler noch stecken soll.

Now liefert ein TDateTime zurück. Zwar kann TDateTime auch Millisekunden speichern, aber Now rundet immer auf volle Sekunden (siehe Delphi-Hilfe). Die Frage ist also, ob man mit der Differenz Now - NL überhaupt sinnvoll rechnen kann. Hinzu kommt noch der große Teiler "Now-NL)*86400".
Das hier funktioniert:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
// uses MMSystem
procedure TMainform.Button1Click(Sender: TObject);
var
  Zeit  : TDateTime;
  Zeit1 : TDateTime;
  Zeit2 : TDateTime;
begin
  Zeit1 := TimeGetTime;
  Sleep(24);
  Zeit2 := TimeGetTime;
  Zeit := (Zeit2 - Zeit1);
  if Zeit > 0 then
    Label1.Caption := FloatToStr(Round((1 / Zeit) * 1000))
  else
    Label1.Caption := 'Zeit = 0!';
end;


Boldar - Di 09.04.13 20:26

Warum nicht gettickcount?


Gerd Kayser - Di 09.04.13 20:28

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Warum nicht gettickcount?

TimeGetTime hat eine höhere Auflösung.


Boldar - Di 09.04.13 20:35

Dann halt Queryperformancecounter. Btw. hat Timegettime nicht unbedingt eine höhere Präzision, und Auflösung ist sowieso das falsche Wort.
Zudem die Frage ob der TE das hier braucht, und nicht lieber einfach mehrere Frames messen möchte. Scheinbar hat der TE mit seinem Timer aber eh ein generelles Konzeptproblem.


Gerd Kayser - Di 09.04.13 20:44

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Auflösung ist sowieso das falsche Wort.

Zitat:
The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds.

Quelle: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724408(v=vs.85).aspx
Ich übersetze Resolution mit Auflösung. Aber das ist Erbsenzählerei.


WasWeißDennIch - Di 09.04.13 21:43

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Zudem die Frage ob der TE das hier braucht, und nicht lieber einfach mehrere Frames messen möchte. Scheinbar hat der TE mit seinem Timer aber eh ein generelles Konzeptproblem.

Das sag ich doch die ganze Zeit.


Mathematiker - Di 09.04.13 23:09

Hallo,
user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Dann halt Queryperformancecounter.

Genau. Und deshalb wiederhole ich noch einmal meinen Vorschlag:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var Time1, Time2, Freq: Int64;
    wert : extended;
begin
    QueryPerformanceFrequency(Freq);
    QueryPerformanceCounter(Time1);

    //hier Deine Zeichnung

    QueryPerformanceCounter(Time2);
    wert:=1000*(Time2-Time1)/freq;
    label1.caption:=floattostrf(wert,ffgeneral,4,3)+' ms';
    label2.caption:=floattostrf(1000/wert,ffgeneral,4,3)+' Bilder je s';
end;

Das funktioniert garantiert. Und wenn es nicht in die Zeichenroutine eingebaut werden soll, dann macht zwei Prozeduren, eine zum Start und eine zur Auswertung. Damit gibt's auch keinen Timer mehr, der offensichtlich nicht so will, wie er soll.

Beste Grüße
Mathematiker


Martok - Mi 10.04.13 07:01

Was die Auflösungen der verschiedenen Zeitfunktionen angeht... das müsste mal wer untersuchen. Oh wait, hat ja schon wer gemacht [http://www.entwickler-ecke.de/viewtopic.php?p=674768#674768] ;-)

Der Timer an sich wird schon funktionieren, hat unterhalb von einigen 100ms allerdings genau gar keine Wiederholgenauigkeit mehr. Das ist also durchaus möglich, dass manchmal sofort und manchmal erst nach relativ langer Zeit wieder ein Event kommt. Was als Renderschleife allerdings mehr oder weniger egal ist - ein Timer mir sehr kurzer Auflösung feuert praktisch genauso oft wie eine IdleLoop. Man kann dann allerdings auch direkt diese nehmen...

Und ansonsten das was Mathematiker sagt, siehe Link. An QPC führt kein Weg vorbei.

Momentanframeraten sind übrigens relativ nutzlos, die sollte man schon mitteln. FrameTime dagegen ist was, was durchaus seine Berechtigung hat.