Korrekt.
Und wenn deine Zahlen immer aus 4 Zeichen bestehen dann hast du enormes Glück gehabt denn du kannst sehr schnell positionieren. Das kann unter Umständen dir dabei helfen deine 8 Millionen Zahlen quasi in parallel abzuarbeiten. Dazu teilst du die Datei in sagen wir mal 20 kleinere Dateien die eine Größe besitzen die ein Vielfaches von 4 * 20 ist. 4 weil deine Zahlen ja immer aus 4 zeichen bestehen und * 20 weil du ja immer 20 solcher Zahlen bewerten möchtest.
Du kannst also ohne großen Aufwand die Verarbeitung mit mehreren CPUs bzw. Rechnern beschleunigen. Denn 8 Millionen Zahlen sind nicht wenige Zahlen, und selbst die schnellste Umsetzung als program wird denoch einiges an Reechenzeit benötigen.
Du solltest jetzt einfach folgendes abändern:
Delphi-Quellcode:
procedure ProcessFile(
const AFilename:
String; AOffset,ACount: Integer);
// AOffset = Index der Zahl mit der begonnen werden soll, jede Zahl besteht aus 4 Zeichen in der Datei
// ACount = Anzahl der Zahlen die berechnet werden sollen
const
BufferSize = 1024 * 4;
var
Stream: TFileStream;
Buffer:
String;
Value: Integer;
// aktuelle Zahl in der Datei
ValueSign: Integer;
// Vorzeichen von Value
ValueCount: Integer;
// Anzahl der gelesenen Zahlen aus der Datei
ValueValid: Boolean;
// enthält Value eine gültige Zahl ?
Avg: Double;
// kummulierte Summe aller Zahlen -> Avg / ValueCount == Durchschnitt
Dev: Double;
// kummulierte Quadrate aller Zahlen -> Dev * ValueCount - Avg / (ValueCount * (ValueCount -1)) == Standardabweichung
CurChar,EndChar: PChar;
// Anfang/Ende des Buffer
Symbol: Char;
// aktuell auszuwertende Ziffer/Buchstabe
procedure Calculate;
begin
Value := Value * ValueSign;
Avg := Avg + Value;
Dev := Dev + Sqr(Value);
Inc(ValueCount);
if ValueCount = 20
then
begin
// Standardabweichung/Durchschnitt berechnen
Dev := (Dev * 20 - Sqr(Avg)) / (20*19);
Avg := Avg / 20;
// hier Werte Avg/Dev speichern oder so...
// alle kumulativen Werte auf 0 setzen
ValueCount := 0;
Avg := 0;
Dev := 0;
end;
ValueValid := False;
Value := 0;
ValueSign := +1;
Dec(ACount);
end;
begin
// initialisierung
CurChar :=
nil;
EndChar :=
nil;
Value := 0;
ValueSign := +1;
ValueValid := False;
ValueCount := 0;
Avg := 0;
Dev := 0;
// Buffer allozieren, Stream öffnen
SetLength(Buffer, BufferSize);
Stream := TFileStream.Create(AFilename, fmOpenRead
or fmShareDenyNone);
try
Stream.Position := AOffset * 4;
repeat
// solange noch Zeichen im Buffer diese in Zahlen umwandeln
while (CurChar < EndChar)
and (ACount > 0)
do
begin
Symbol := CurChar^;
if Symbol
in ['
0'..'
9']
then
begin // String in Zahl umwandeln
Value := Value * 10 + Ord(Symbol) - Ord('
0');
ValueValid := True;
end else
if ValueValid
then // falls in Value eine gültige Zahl war diese in Avg/Dev kummulieren
Calculate
else
if Symbol = '
-'
then
ValueSign := -1;
Inc(CurChar);
end;
// Buffer aus Datei laden
CurChar := PChar(Buffer);
EndChar := CurChar + Stream.
Read(Buffer[1], BufferSize);
until (EndChar = CurChar)
and (ACount <= 0);
if ValueValid
then // letzte eventuell nicht per Leerzeichen abgeschlossene Zahl berücksichtigen
Calculate;
finally
Stream.Free;
end;
end;
Gruß Hagen
[edit]
Da fällt mir ein das du aber sehr aufpassen musst. Betrachte deine Datei nochmal genau mit einem HEX Editor ob wirklich nur Zahlen in 4 Zeichen Gruppen darin vorkommen. Im speziellen beziehe ich mich auf den Zeilenumbruch, Zeilenvorschub -> Carrige Return, Linefeed -> #13,#10 und eventuell Tabs -> #9. Solche Sonderzeichen sollten darin nicht enthalten sein !
[/edit]