![]() |
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?? |
Re: Moving Average
hi,
scheint mir momentan nicht so die mathematische Hürde zu sein. Woran hapert es denn genau? |
Re: Moving Average
Hallo,
da die Zahlen im StringGrid als Zeichenketten vorliegen, musst du sie erst konvertieren:
Delphi-Quellcode:
Als Parameter strings kannst du z.B. StringGrid.Rows[iRow] oder StringGrid.Cols[iCol] übergeben.
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; Die Berechnung des gleitenden Durchschnitts ist dann wahrscheinlich nicht mehr dein Problem.
Delphi-Quellcode:
Getippt und nicht getestet.
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; Grüße vom marabu |
Re: Moving Average
Zitat:
zeig doch mal her, was du bereits hast, und wo es hackt ... |
Re: Moving Average
Ich tippe mal auf ein Mehrschleifenproblem wobei die 2.Schleife das Problem darstellt.
Delphi-Quellcode:
i : ist die Laufvariable für das Stringgrid
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; 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. |
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; |
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. |
Re: Moving Average
Sorry,
da war ein Fehler drin - ich habe ihn korrigiert. Hier noch die Variante ohne die Funktion Mean():
Delphi-Quellcode:
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.
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;
Delphi-Quellcode:
Für FixedRows > 0 müssen die Signaturen der Konvertierfunktionen noch um einen entsprechenden skip value erweitert werden.
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; Freundliche Grüße |
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. |
Re: Moving Average
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:03 Uhr. |
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