Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#20

Re: Mittelwert und Standardabweichung

  Alt 24. Apr 2006, 23:12
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]
  Mit Zitat antworten Zitat