Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Moving Average (https://www.delphipraxis.net/119366-moving-average.html)

fl63 25. Aug 2008 14:34


Moving Average
 
Hallo DPler


Heute eine Frage an alle Mathematiker unter Euch.
Wie Programmiert man einen laufenden Durchschnitt:
zB. Durchschitt aus drei Werten erster Durchschitt //kein Problem
Durchschnitt aus dem 2. 3. und 4.Wert zweiter Durchschnitt
Durchschnitt aus dem 3. 4. und 5.Wert

usw.
Also unten einen Wert hinzu und oben einen Fallenlassen.
Soweit kein Problem aber wie programmiere ich soetwas in einem Stringgrid??

angos 25. Aug 2008 15:30

Re: Moving Average
 
hi,

scheint mir momentan nicht so die mathematische Hürde zu sein. Woran hapert es denn genau?

marabu 25. Aug 2008 17:36

Re: Moving Average
 
Hallo,

da die Zahlen im StringGrid als Zeichenketten vorliegen, musst du sie erst konvertieren:

Delphi-Quellcode:
uses
  Math,
  Types;

procedure DataToStrings(data: TDoubleDynArray; strings: TStrings; const fmt: string = '%f');
var
  i: Integer;
begin
  strings.Clear;
  for i := Low(data) to High(data) do
    strings.Add(Format(fmt, [Data[i]]));
end;

function StringsToData(strings: TStrings; default: Double = 0): TDoubleDynArray;
var
  i: Integer;
begin
  SetLength(Result, strings.Count);
   for i := Low(Result) to High(Result) do
     Result[i] := StrToFloatDef(strings[i], default);
end;
Als Parameter strings kannst du z.B. StringGrid.Rows[iRow] oder StringGrid.Cols[iCol] übergeben.

Die Berechnung des gleitenden Durchschnitts ist dann wahrscheinlich nicht mehr dein Problem.
Delphi-Quellcode:
uses
  Math,
  Types;

function SimpleMovingAverage(data: TDoubleDynArray; n: Word): TDoubleDynArray;
var
  i: Integer;
  temp: TDoubleDynArray;
begin
  SetLength(Result, Length(data));
  for i := Low(data) to High(data) do
  begin
    if i < n
      then temp := Copy(data, 0, Succ(i)) // was: i (off by one)
      else temp := Copy(data, Succ(i - n), n);
    Result[i] := Mean(temp);
  end;
end;
Getippt und nicht getestet.

Grüße vom marabu

grenzgaenger 25. Aug 2008 21:52

Re: Moving Average
 
Zitat:

Zitat von fl63
Hallo DPler


Heute eine Frage an alle Mathematiker unter Euch.
Wie Programmiert man einen laufenden Durchschnitt:
zB. Durchschitt aus drei Werten erster Durchschitt //kein Problem
Durchschnitt aus dem 2. 3. und 4.Wert zweiter Durchschnitt
Durchschnitt aus dem 3. 4. und 5.Wert

usw.
Also unten einen Wert hinzu und oben einen Fallenlassen.
Soweit kein Problem aber wie programmiere ich soetwas in einem Stringgrid??

und wo liegt das problem? :glaskugel:


zeig doch mal her, was du bereits hast, und wo es hackt ...

fl63 26. Aug 2008 11:24

Re: Moving Average
 
Ich tippe mal auf ein Mehrschleifenproblem wobei die 2.Schleife das Problem darstellt.

Delphi-Quellcode:
procedure TForm1.Button6Click(Sender: TObject);
Var i,k,Summe :Integer;
  Durchschnitt:Extended;
begin
  Summe := 0;
    For i := 0 to SG1.RowCount-1 do
       begin
           k := 0;
           For k := k - (StrToInt(Edit2.Text)) to (SG1.RowCount-1 - StrToInt(Edit2.Text)) do
             begin
             If k <= 0 do
               Summe := Summe + StrToInt(SG1.Cells[1,k]);
             If k = 0 do
               Summe := Summe + StrToInt(SG1.Cells[1,k]);
             If k >= 0 do
               Summe := Summe + StrToInt(SG1.Cells[1,k]);

             if k = StrToInt(Edit2.Text) then break;
             end;
           Durchschnitt := Summe / StrToInt(Edit2.Text);
           SG1.Cells[3,k] := FloatToStr(Durchschnitt);
       end;
end;
i : ist die Laufvariable für das Stringgrid
k : Edit2.Text Die Glättungsvariable(Durchschnitt) je höher desto geringer der Einfluß der einzelnen Meßgröße.

Die Konvertierung erfolgt doch durch InttoStr, FloattoStr usw.

angos 26. Aug 2008 12:42

Re: Moving Average
 
Hi,

schau dir das mal an. musst du dann nur noch für dich abändern

Delphi-Quellcode:
var
  ir, ic, i, iDurchschnitt: Integer;
  val1, val2, val3: String;
begin

  for ir := 0 to grd.RowCount - 1 do
  begin
    for ic := 0 to grd.RowCount - 1 do
    begin
      if ((ir = 0) and (ic = 0))
        or ((ir = grd.RowCount-1) and (ic=grd.ColCount-1)) then Continue;

      if ic = 0 then
        val1 := grd.Cells[grd.ColCount-1, ir-1]
      else
        val1 := grd.Cells[ic-1, ir];

      val2 := grd.Cells[ic, ir];

      if ic = grd.ColCount-1 then
        val3 := grd.Cells[0, ir+1]
      else
        val3 := grd.Cells[ic+1, ir];

   
      idDurchschnitt := (InttoStr(val1) + InttoStr(val2) + InttoStr(val3)) / 3;

    end;
  end;
end;

fl63 26. Aug 2008 15:48

Re: Moving Average
 
Bei der function simple moving average von Marabu komme ich irgendwie nicht sehr weit.
Meine clickprocedure liefert irgenwelche Fehler, jedenfalls kein gleitenden Durchschnitt.

marabu 26. Aug 2008 17:53

Re: Moving Average
 
Sorry,

da war ein Fehler drin - ich habe ihn korrigiert.

Hier noch die Variante ohne die Funktion Mean():

Delphi-Quellcode:
function SimpleMovingAverage(data: TDoubleDynArray; n: Word): TDoubleDynArray;
var
  i: Integer;
  dSum: Double;
begin
  SetLength(Result, Length(data));
  dSum := 0;
  for i := Low(data) to High(data) do
  begin
    if i >= n then
      dSum := dSum - data[i - n];
    dSum := dSum + data[i];
    if i < n
      then Result[i] := dSum / Succ(i)
      else Result[i] := dSum / n;
  end;
end;
Denke bitte daran, dass der Code nur die Strukturierung des Problems durch Prozeduren und Funktionen zeigen soll. Getestet habe ich mit einem StringGrid ohne FixedRows.

Delphi-Quellcode:
const
  FMT = '%.1f';

procedure TDemoForm.InitButtonClick(Sender: TObject);
var
  i: Integer;
begin
  with StringGrid do
    for i := FixedRows to Pred(RowCount) do
      Cells[FixedCols, i] := Format(FMT, [Random * 100]);
end;

procedure TDemoForm.CalcButtonClick(Sender: TObject);
var
  data, sma: TDoubleDynArray;
begin
  with StringGrid do
  begin
    data := StringsToData(Cols[FixedCols]);
    sma := SimpleMovingAverage(data, 3);
    DataToStrings(sma, Cols[Succ(FixedCols)], FMT);
  end;
end;
Für FixedRows > 0 müssen die Signaturen der Konvertierfunktionen noch um einen entsprechenden skip value erweitert werden.

Freundliche Grüße

fl63 27. Aug 2008 16:41

Re: Moving Average
 
Hallo Marabu,

Was ist ein Skip Value??
Deine Proceduren laufen einwandfrei, dennoch habe ich ein paar Fragen:

1. n ist als Word deklariert Ich möchte eine Variable StrtoWord(edit1.text). StrToWord aus der Unit IdTrivialFTPBase funktioniert nicht. Also wie bekomme ich Edit1.text in Word konvertiert?
Vielleicht liegt es an der falschen Unit, sie ist aus der Delphi-Hilfe.

2. Die Ausgabe der Ergebnisse müssen ein paar Spalten weiter angezeigt werden.
FixedCol Problem. Wenn ich Unter CalcButtonClick DatatoStrings(sma(Cols[4]..) eingebe erscheinen gar keine Ergebnisse in der Spalte.

Bitte Hilfe.

DeddyH 27. Aug 2008 16:48

Re: Moving Average
 
Zitat:

Zitat von fl63
Also wie bekomme ich Edit1.text in Word konvertiert?

Mit StrToInt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:03 Uhr.
Seite 1 von 3  1 23      

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