# Werte im array verschieben



## fiftyone_88 (13 Oktober 2015)

Hallo miteinander, ich habe einen array mit 10 Plätzen und möchte, das der aktuelle wert immer auf dem ersten Platz ist und die restlichen sich um einen verschieben.

Beispiel:

Programmstart, erster Wert ist 1
2ter Durchlauf, aktueller Wert ist 2 
.
.
10ter Durchlauf, aktueller Wert ist 10

Also beim Programmstart: 1,0,0,0,0,0,0,0,0,0,0

2ter Durchlauf: 2,1,0,0,0,0,0,0,0,0,0

10ter Durchlauf: 10,9,8,7,6,5,4,3,2,1

Beim 11ten nehmen wir mal an, der aktuelle Wert sei 5 dann sollte es so aussehen: 5,10,9,8,7,6,5,4,3,2

Ich habe es so geschrieben geht das?

FOR i:=1 TO 9 BY 1 DO vMerker[i+1]:=vMerker_; END_FOR; (*verschiebt den ersten wert auf den zweiten usw*)
vMerker[1]:=v; (*aktueller wert wird auf den ersten geschrieben*)

Geht das so? Oder würde beim ersten Durchlauf der Schleife der 1te Wert auf den 2ten geschrieben werden und beim zweiten Durchlauf der 2te Wert auf den 3ten? Das würde ja bedeuten, das er alle plätze mit dem 1ten wert füllt oder?


Dann möchte ich den Mittelwert des array Werte bilden.

FOR i:=1 TO 10 BY 1 DO sumMerker:=sumMerker+vMerker; END_FOR; (*zählt alle zsm*)
vMittelwert:=sumMerker*0.1;(*summe wird durch 10 geteilt*)

Ich bedanke mich schonmal für eure Hilfe._


----------



## hucki (13 Oktober 2015)

fiftyone_88 schrieb:


> Ich habe es so geschrieben geht das?
> 
> FOR i:=1 TO 9 BY 1 DO vMerker[i+1]:=vMerker_; END_FOR; (*verschiebt den ersten wert auf den zweiten usw*)
> vMerker[1]:=v; (*aktueller wert wird auf den ersten geschrieben*)
> ...


_Letzteres.

Du musst demzufolge mit dem Verschieben im Array hinten anfangen:


		Code:
	

[COLOR=#333333]FOR i:= 9 TO 1 BY -1 DO
[/COLOR]    [COLOR=#333333]vMerker[i+1]:= vMerker[i];
END_FOR;[/COLOR]

_


----------



## hucki (13 Oktober 2015)

fiftyone_88 schrieb:


> Dann möchte ich den Mittelwert des array Werte bilden.
> 
> FOR i:=1 TO 10 BY 1 DO sumMerker:=sumMerker+vMerker_; END_FOR; (*zählt alle zsm*)
> vMittelwert:=sumMerker*0.1;(*summe wird durch 10 geteilt*)_


_Hier solltest Du vor der FOR-Schleife die Variable sumMerker noch sicherheitshalber auf 0 setzen, sonst könnte im 2. Programmdurchlauf noch die Summe des 1. Durchlaufs drin stehen und mit zu den 10 aktuellen Werten addiert werden.
Hängt von der Deklarierung von sumMerker ab._


----------



## fiftyone_88 (13 Oktober 2015)

hucki schrieb:


> Hier solltest Du vor der FOR-Schleife die Variable sumMerker noch sicherheitshalber auf 0 setzen, sonst könnte im 2. Programmdurchlauf noch die Summe des 1. Durchlaufs drin stehen und mit zu den 10 aktuellen Werten addiert werden.
> Hängt von der Deklarierung von sumMerker ab.



zu beiden antworten vielen dank, ja sumMerker setze ich nach dem der mittelwert berechnet wurde auf 0


----------



## PN/DP (14 Oktober 2015)

Damit die Berechnung auch beim ersten Mal bzw. immer garantiert korrekt ist solltest Du sumMerker *VOR* der Berechnung auf 0 setzen.

Harald


----------



## fiftyone_88 (14 Oktober 2015)

iat bei der variablen deklaration direkt auf null gesetzt


----------



## fiftyone_88 (14 Oktober 2015)

PN/DP schrieb:


> Damit die Berechnung auch beim ersten Mal bzw. immer garantiert korrekt ist solltest Du sumMerker *VOR* der Berechnung auf 0 setzen.
> 
> Harald




eine frage noch, und zwar wenn ich ein 10 min mittelwert bilden möchte, kann ich das dann so machen:

zehnminTakt.PT:=T#600s;
zehnminTakt.IN:=NOT zehnminTakt.Q;
IF (zehnminTakt.Q=FALSE) 
    THEN zehnminSumme:=zehnminSumme+v; z:=z+1;
    ELSE v10Mittelwert:=zehnminSumme/z; zehnminSumme:=0;
END_IF;


----------



## PN/DP (14 Oktober 2015)

Um ganz sicher zu gehen initialisiert man Variablen trotzdem VOR der Verwendung. 
Außerdem könntest Du die Variable durch eine temporäre Variable ersetzen und dann MUSST Du sie vor der Verwendung initialisieren.

Harald


----------



## MasterOhh (14 Oktober 2015)

fiftyone_88 schrieb:


> eine frage noch, und zwar wenn ich ein 10 min mittelwert bilden möchte, kann ich das dann so machen:
> 
> zehnminTakt.PT:=T#600s;
> zehnminTakt.IN:=NOT zehnminTakt.Q;
> ...



Ja so kannst du einen Mittelwert über die letzten 10 Minuten bilden. Du erhälst aber nur alle 10 Minuten einen neuen Wert, wenn dir das reicht....
Ansonsten befasse dich mal mit dem Thema "gleitender Mittelwert". Ich denke dazu findest du hier im Forum auch schon die ein oder andere Lösung.


----------



## Caroli (14 Oktober 2015)

Wenn Du einen 10min Mittelwert bilden willst, kannst Du die For.. Schleife 1mal je min für 1 Zyklus aufrufen.


----------



## fiftyone_88 (14 Oktober 2015)

MasterOhh schrieb:


> Ja so kannst du einen Mittelwert über die letzten 10 Minuten bilden. Du erhälst aber nur alle 10 Minuten einen neuen Wert, wenn dir das reicht....
> Ansonsten befasse dich mal mit dem Thema "gleitender Mittelwert". Ich denke dazu findest du hier im Forum auch schon die ein oder andere Lösung.



ok danke. ja den gleitenden mittelwert bilde ich mit den letzten 10 werten (ganz am anfang des threads) diesen 10 min mittelwert brauche ich für ein histogramm, das system soll theoretische jahrelang laufen, und alle 10 min mitteln.


----------



## fiftyone_88 (14 Oktober 2015)

Caroli schrieb:


> Wenn Du einen 10min Mittelwert bilden willst, kannst Du die For.. Schleife 1mal je min für 1 Zyklus aufrufen.



wie funktioniert das? habe das mit zeitlichen angaben nie gesehen


----------



## Caroli (14 Oktober 2015)

(*..geht wieder über den Timer..*)

VAR
minTimer:ton;
end_var

minTimer(PT:=t#1m);
minTimer.IN:=not minTimer.Q;

IF minTimer.Q THEN
 (*hier packst Du die FOR.. ..END_FOR Sachen rein*);
END_IF


----------



## fiftyone_88 (14 Oktober 2015)

Caroli schrieb:


> (*..geht wieder über den Timer..*)
> 
> VAR
> minTimer:ton;
> ...




vielen dank, schaue ich mir mal genauer an


----------



## singleton (14 Oktober 2015)

Hi,
warum verwendest Du nicht einen Ringpuffer anstatt jedesmal das komplette Array zu kopieren?
Das mag bei 10 Werten keine große Sache sein, aber wenn das Array mal größer sein sollte...


```
Index := (Index MOD 10) + 1;
vMerker[Index] := v;
```


----------



## fiftyone_88 (14 Oktober 2015)

singleton schrieb:


> Hi,
> warum verwendest Du nicht einen Ringpuffer anstatt jedesmal das komplette Array zu kopieren?
> Das mag bei 10 Werten keine große Sache sein, aber wenn das Array mal größer sein sollte...
> 
> ...


 
das habe ich nicht genau verstanden. kannst du das bisschen erläutern bitte.


----------



## fiftyone_88 (14 Oktober 2015)

es funktioniert irgendwie nicht :/


----------



## PN/DP (14 Oktober 2015)

fiftyone_88 schrieb:


> es funktioniert irgendwie nicht :/


Ich verstehe irgendwie nicht was Du meinst 

Harald


----------



## fiftyone_88 (14 Oktober 2015)

PN/DP schrieb:


> Ich verstehe irgendwie nicht was Du meinst
> 
> Harald



Er verschiebt die Werte irgendwie nicht. i wird auf 11 gesetzt und die werten nehmen den vom ersten arrayplatz an.

hier mein Quellcode. vielleicht  mache ich bei der variablen deklaration falsch?

VAR
    signal:BOOL;
    sTakt:TON;

    flanke:F_TRIG;
    f,v,sumMerker,vGMittelwert:REAL:=0;
    n:Real:=0;
    vMerker:ARRAY[1..10] OF REAL;
    i:BYTE;
END_VAR

signal:=PiFace.byIn.1;
sTakt(PT:=T#1S);
zehnminTakt(PT:=T#600S);
sTakt.IN:=NOT sTakt.Q;

flanke(CLK:=signal);
IF (flanke.Q) THEN n:=n+1; END_IF;
IF (sTakt.Q) THEN f:=n; n:=0; END_IF;

v:=0.048*f;

FOR i:=9 TO 1 BY 1 DO vMerker[i+1]:=vMerker_; END_FOR;
FOR i:=1 TO 10 BY 1 DO sumMerker:=sumMerker+vMerker; END_FOR;
vGMittelwert:=sumMerker*0.1;
sumMerker:=0;_


----------



## hucki (14 Oktober 2015)

fiftyone_88 schrieb:


> ```
> FOR i:=9 TO 1 BY [COLOR=#ff0000][U][B]1[/B][/U][/COLOR] DO vMerker[i+1]:=vMerker[i]; END_FOR;
> ```


Wenn die Schleife rückwärts durchlaufen werden soll, muss die Schrittweite im Minusbereich sein. Hier also -1 und nicht 1.


Und benutz' für Deine Programmauszüge bitte die Code-Tags *[Code] ... [/Code]*, die Du z.B. mit dem letzten Button # in der 2. Zeile erzeugen kannst. Dann wird der Code besser lesbar dargestellt.


----------



## fiftyone_88 (14 Oktober 2015)

hucki schrieb:


> Wenn die Schleife rückwärts durchlaufen werden soll, muss die Schritrtweite im Minusbereich sein. Hier also -1 und nicht 1.
> 
> 
> Und benutz' für Deine Programmauszüge bitte die Code-Tags *[Code] ... [/Code]*, die Du z.B. mit dem letzten Button # in der 2. Zeile erzeugen kannst. Dann wird der Code besser lesbar dargestellt.



ups   danke


----------



## hucki (14 Oktober 2015)

fiftyone_88 schrieb:


> das habe ich nicht genau verstanden. kannst du das bisschen erläutern bitte.


Es gibt 2 Möglichkeiten ein FIFO anzulegen.

Die 1. entspricht Deiner:
Der Zeiger für den neuen Wert zeigt immer auf die erste Stelle. Vor dem Eintragen werden die Werte um eins verschoben.
Nachteil: Zeitaufwendig
Vorteil: feste Reihenfolge, z.B. wenn die Werte der Reihe nach visualisiert werden sollen


Die 2. Variante:
Die Werte werden nicht verschoben, sondern nur der Zeiger, wo der nächste Wert eingetragen wird, wird jedes mal um eins weiter gezählt.
Beim 1. Speichern wird also in die 1. Zelle eingetragen, der 2. ind die 2. Zelle ...
Wenn man an der letzten Zelle angekommen ist, wird wieder von vorn angefangen. So wird auch hier der älteste Wert überschrieben (raus geschoben)
Vorteil:  vor allem bei großen Datenmengen wesentlich schneller.
Nachteil: Der Startindex für das FIFO ändert sich, was eine Visualisierung schwieriger macht.


Du willst nur einen Mittelwert über alles, da ist die Reihenfolge im FIFO egal.
Bei 10 Werten merkt man da zwischen den beiden Varianten noch nicht wirklich einen Unterschied. Wenn's jedoch in die Tausende geht, bekommt man bei der 1. Variante eventuell Probleme mit der Zykluszeit.


----------



## fiftyone_88 (15 Oktober 2015)

hucki schrieb:


> Es gibt 2 Möglichkeiten ein FIFO anzulegen.
> 
> Die 1. entspricht Deiner:
> Der Zeiger für den neuen Wert zeigt immer auf die erste Stelle. Vor dem Eintragen werden die Werte um eins verschoben.
> ...




ja deine variante gefällt mir sehr, danke. eine frage kann mann die anzahl der arrays durch eine variable definieren? siehe beispiel 


```
VAR
 i:INT:0; 
n:INT:=20;
vMerker:ARRAY[1..n] OF REAL;
 END_VAR

i:=(i MOD n)+1; 
vMerker[i]:=v;
```


----------



## hucki (15 Oktober 2015)

fiftyone_88 schrieb:


> eine frage kann mann die anzahl der arrays durch eine variable definieren? siehe beispiel
> 
> 
> ```
> ...


Nein, nur durch eine Konstante.

Das Array wird schon beim Übersetzen gebildet, daher keine Variable.


----------



## singleton (16 Oktober 2015)

Sollte Dein Laufzeitsystem __New unterstützen, könntest Du das Array auch dynamisch zur Laufzeit erzeugen.


----------

