Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Problem mit Fraktion/Prozentrechnung (https://www.delphipraxis.net/46327-problem-mit-fraktion-prozentrechnung.html)

DGL-luke 22. Mai 2005 22:09


Problem mit Fraktion/Prozentrechnung
 
Ich mach gerade ne kleine Anwendung, die mir n paar statistische Sachen über eine(n) text(datei) gibt. naja, eigentlich berechnet sie zur zeit nur die verteilung der buchstaben:

Delphi-Quellcode:
procedure TForm1.BCheckClick(Sender: TObject);
var c:char;
    counts:array[0..25] of integer;
    fraction:array[0..25] of single;
    i,k:integer;
    PB:TRBProgressBar;
begin
for PB in bars do
 PB.Position:=0;                                   //Ja, Marabu und Sakura, seht nur hin, ich weise der Schleifenvariable etwas zu ;)

for i:= 0 to length(counts)-1 do                   //initialize the array
 counts[i]:=0;

for i := 1 to memo1.GetTextLen do
 begin
  application.ProcessMessages;                      //damit das ganze nicht hängenbleibt
  c:=memo1.text[i];                                 //dem char wird ein buchstabe des memos zugewiesen.
  c:=ansilowercase(c)[1];                           //der char wird kleingemacht. was passiert eigentlich wenn er z.b. #10 ist? das muss ich gleich noch alles überprüfen/abfangen.
  PBSum.Position:=round(i / memo1.GetTextLen * 100); //hier kommt der gesamtfortschritt raus.
  counts[ord(c)-97]:=counts[ord(c)-97]+1;           //wenn c=#97='a' ist, wird counts[97-97] inkrementiert.
 end;

for i:= 0 to 25 do
 fraction[i]:=counts[i]/memo1.GetTextLen;           //hier werden die anteile an der gesamtdatei berechnet.

for i:= 0 to 100 do                                 //diese schleife ist eigentlich nur design.
 for k:= 0 to 25 do
  begin
   application.ProcessMessages;                     //noch einmal antifreeze :D
   if bars[k].Position < round(fraction[k]*100) then //wenn die progressbar noch nicht soweit ist wie es der anteil sagt, dann...
    bars[k].Position:=bars[k].Position + 1;         //...wird position inkementiert.
  end;
end;
1. ja die performance ist schlecht. danach frag ich aber gar nicht. oder doch: wenn ich progressmessages nicht so oft aufrufe, wirkt sich das auf die performance aus, oder werden sowieso alle anstehenden messages abgearbeitet?
2. das eigentliche problem:
es funktioniert alles wunderbar, aber ich bekomm zum schluss immer nur ganz mickrige anteile raus. in der summe ergibt es nie auch nur annähernd hundert (zeilenumbrüche muss man ja rausrechnen). es bewegt sich so zwischen 60% und 80%, wobei 60% typisch ist. die linefeeds machen 2-4% aus. ich hab also irgendwo was falsch. evtl. irgendwo so gravierende rundungsfehler? die bars werden ja in der letzten schleife zugewiesen. das sieht für mich aber ganz richtig aus?!

EDIT: gerade nen testlauf gemacht mit einfach nur 'aaaaaaa...'. gibt er mir brav meine 100%. also doch n rundungsfehler?!
EDIT2: liegt es vielleicht doch an den ganzen sonderzeichen('(', '-','_' usw.) die sich in so nem textfile verstecken? hab jetzt noch n paar solche testfälle laufen gelassen, und da geht es.

Minz 23. Mai 2005 00:54

Re: Problem mit Fraktion/Prozentrechnung
 
2 Stellen kommen mir komisch vor:

Zitat:

Delphi-Quellcode:
PBSum.Position:=round(i / memo1.GetTextLen * 100);

müsste es nicht 100/memo1.GetTextLen*i; sein?

als Alternative könntest du dir das aber auch sparen, wenn du die Progressbar-Länge auf die Memo-Länge setzt, und mit jedem i, PBSum.Step machst.

Zitat:

Delphi-Quellcode:
fraction[i]:=counts[i]/memo1.GetTextLen;

Sollte der Anteil nicht eine Prozentangabe sein? Ist ja klar, dass du so eine sehr kleine Zahl bekommst, weil es immer z=x/y, y>x ist und damit z<1 ist
Delphi-Quellcode:
fraction[i]:=100/memo1.GetTextLen*counts[i];

Robert_G 23. Mai 2005 05:57

Re: Problem mit Fraktion/Prozentrechnung
 
ot:
Zitat:

PB.Position:=0; //Ja, Marabu und Sakura, seht nur hin, ich weise der Schleifenvariable etwas zu ;)
Nope, der Zeiger der Variable ist constant, das hindert dich aber nicht daran ihre Properties zu besetzen. ;) (Das ganze wäre auch sinnlos, wenn das nicht ginge :shock: )

jim_raynor 23. Mai 2005 08:35

Re: Problem mit Fraktion/Prozentrechnung
 
Zitat:

Zitat von DGL-luke
1. ja die performance ist schlecht. danach frag ich aber gar nicht. oder doch: wenn ich progressmessages nicht so oft aufrufe, wirkt sich das auf die performance aus, oder werden sowieso alle anstehenden messages abgearbeitet?

Ja, es wirkt sich sehr negativ aus. Mein Vorschlag: Es sollte reichen, wenn du alle 10000 Zeichen oder so mal ein ProcessMessage machst. Nimms mal raus und es wird erheblich schneller laufen ;)

shmia 23. Mai 2005 09:11

Re: Problem mit Fraktion/Prozentrechnung
 
So bleibt extrem viel Performance auf der Strecke, da bei Aufruf von memo1.Text
jedesmal alle Zeichen geholt werden.
Das Property TMemo.Text mag ja aussehen, als ob es ein gewöhnlicher String wäre;
intern ist aber ein relativ hoher Aufwand nötig, diesen String zu liefern.
Delphi-Quellcode:
for i := 1 to memo1.GetTextLen do
begin
  application.ProcessMessages;                      //damit das ganze nicht hängenbleibt
  c:=memo1.text[i];                                 //dem char wird ein buchstabe des memos zugewiesen.
  c:=ansilowercase(c)[1];
deutlich schneller:
Delphi-Quellcode:
var
   s : string;
...
   s := AnsiLowerCase(memo1.Text); // Daten aus Memo in einem Rutsch holen und gleich in Kleinbuchstaben wandeln
for i :=1 to Length(s) do
begin
   c := s[i];
   ...

DGL-luke 23. Mai 2005 12:40

Re: Problem mit Fraktion/Prozentrechnung
 
das hört sich ja alles schon ganz vielversprechend an.

@Minz: also das zuweisen von PBSum funktioniert einwandfrei. deshalb werd ich da jetzt auch nichts ändern. fraction ist der anteil aller vorkommen eines zeichens und sollte im regelfall kleiner 1 sein. wenn fraction[65] gleich 0,5 ist, dann besteht exakt die hälfte der textdatei aus 'A's.

@Robert_G: ja, logisch. is mir klar. :-D

@jim_raynor: ok werd ich mal machen. ne einfache if i mod 1000 = 0 then asollte ja reichen.

@shmia: ja, das seh ich mir mal an.

@all: thx!

EDIT: damn, das war jetzt ein schub. und ich hab nur das memo1.text, memo1.gettextlen in ne variable ausgelagert und das processmessages verändert, also nicht so oft aufgerufen. mehr performance brauch ich glaub ich gar nicht. 92 kB in weniger als einer Sekunde. zuvor hab ich mehr als eine Minute gebraucht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:16 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz