Array mit double Werten

Hallo,

es würde mich interessieren, ob es eine elegantere Möglichkeit(mit weniger Rechenaufwand) gibt, ein Array welcher mit double Werten gefüllt ist, um eine Stelle nach links zu verschieben. Das heist, der erste Wert wird durch zweiten, der zweite durch dritten usw. ersetzt.

Hier ist meine Lösung:

if(anzahl_i > N)
{
for(anz_i=0, anl_i=1; anl_i

Hallo,

es würde mich interessieren, ob es eine elegantere
Möglichkeit(mit weniger Rechenaufwand) gibt, ein Array welcher
mit double Werten gefüllt ist, um eine Stelle nach links zu
verschieben. Das heist, der erste Wert wird durch zweiten, der
zweite durch dritten usw. ersetzt.

Hallo Alexander,

kommt drauf an, was das Ganze soll. Für Input/Output-Buffer, gleitende Mittelwertbildung und ähnliche Aufgaben verwende ich Ringpuffer mit jeweils einem Pointer zum Einschreiben und Auslesen. Werte werden eingespeichert mit dem Writepointer pWrite und dieser erhöht; ist pRead pWrite, sind Daten enthalten; am Array-Ende wird der Pointer auf den Anfang gesetzt; holt pWrite den Pointer pRead ein, so ist der Array voll. Sinn der Sache: es werden niemals Werte bewegt, sondern nur Pointer geändert.

Deine Verschiebung ginge noch einfacher: ein Pointer zeigt in den Array, ein neuer Wert wird an diese Stelle geschrieben und der Pointer erhöht (mit Umschlag Ende-Anfang). Dadurch wird der älteste Wert im Array ersetzt. Liest man den Array ab dieser Stelle, erhält man die Werte in der Reihenfolge, wie sie eingespeichert wurden, genau wie wenn man sie im Array nach links geschoben hätte. Man schiebt einfach stattdessen den Anfang des Arrays nach rechts.

Gruss Reinhard

Hallo,

auch …

es würde mich interessieren, ob es eine elegantere
Möglichkeit(mit weniger Rechenaufwand) gibt, ein Array welcher
mit double Werten gefüllt ist, um eine Stelle nach links zu
verschieben. Das heist, der erste Wert wird durch zweiten, der
zweite durch dritten usw. ersetzt.

Wie wär das:

#define SIZE 100
double myArray[SIZE]; // Geht von 0 bis SIZE-1

// ... 

for (int i=0; **i ; i++)  
{  
 myArray[i] = myArray[i+1];  
}**  

Gruß,
Ralf

Hallo Alexander, hallo Reinhard,

wie Reinhard schon schrieb ist meistens die Arrayverschiebung nicht notwendig. Daher also lieber den Grund für dieses Vorhaben posten.

Ansonsten, wenn Du das Array zu jeder Zeit fortlaufend brauchst, dann einfach das Array doppelt so groß anlegen wie gebraucht
float a[2*MAX_IDX], und jeden Wert gleichzeitig an die Stelle

a[idx]=neuerWert;

und

a[idx+ MAX_IDX] = neuerWert;

schreiben.

Mit dem von Reinhard vorgestellten Verfahren, dass der Indexzeiger nach jedem Schreiben um eins erhöht und auf Überlauf abgefragt wird

idx++;
if(idx >= MAX_IDX) idx = 0;

hat man dann zu jeder Zeit einen Zeiger

a[idx]

auf ein aufeinanderfolgendes Array, wobei der erste Wert der älteste ist, der letzte halt der neueste.

Gruß
achim

(Oder alternativ statt idx direkt mit einem pointer auf float arbeiten.)

Hallo,

wie Reinhard schon schrieb ist meistens die Arrayverschiebung
nicht notwendig. Daher also lieber den Grund für dieses
Vorhaben posten.

Grund: bei mir werden kontinuirlich Daten eingelesen (ca. 100000).
Jeder neu eingelesener Wert, wir in ein Array gespeichert und sofort weiter verarbeitet.
Für die Verarbeitung brauche ich mindestens ein Wert und maximun 67Werte. Ist also mein Array mit 67Werten voll, so muss ich Platz für den nächsten eingelesenen Wert freimachen. Die Werte im Array werden also um eine Stelle nach links geschoben, und dadurch der erste Wert durch zweiten usw ersetzt, so entsteht Platz für einen neuen Wert.

Im nächsten Schritt werden die Werte einzeln ausgelesen, mit anderen Werten multipliziert, die entstandenen Produkte werden aufaddiert.

Ansonsten, wenn Du das Array zu jeder Zeit fortlaufend
brauchst, dann einfach das Array doppelt so groß anlegen wie
gebraucht
float a[2*MAX_IDX], und jeden Wert gleichzeitig an die Stelle

a[idx]=neuerWert;

und

a[idx+ MAX_IDX] = neuerWert;

schreiben.

Mit dem von Reinhard vorgestellten Verfahren, dass der
Indexzeiger nach jedem Schreiben um eins erhöht und auf
Überlauf abgefragt wird

idx++;
if(idx >= MAX_IDX) idx = 0;

hat man dann zu jeder Zeit einen Zeiger

das vorgeschlagene Verfahren habe ich leider nicht ganz verstanden, kannst du villeicht ein Beispiel machen.

Danke!!!

MfG,
Alexander

Hallo,

das vorgeschlagene Verfahren habe ich leider nicht ganz
verstanden, kannst du villeicht ein Beispiel machen.

Nehmen wir an, du willst nur 5 Werte speichern. Du hast ein array

double a[5];

und einen Zeiger auf die Position, als der du als nächstes etwas hereinschreiben willst:

int p = 0

Jedes mal, wenn du einen Wert einfügst, erhöhst du p um eins:

void push(double a[5], int p, double new\_val){
 a[p] = new\_val;
 p++;
 p %= 5; /\* Wenn du bei 5 angekommen bist, setze p auf 0 zurueck \*/
}

Das zuletzt eingefügte Element ist bei p-1, wenn p == 0 ist bei 4:

double last\_inserted(double a[5], int p){
 return a[(p + 5 - 1) % 5];
}

Das vorletzte dann entsprechend bei a[(p+5-2) % 5] etc.
Das +5 brauchst du, weil x % 5 für negative x auch negative Werte liefert, Zahlen kleiner 0 sind aber als Index nicht zulässig.

Beispiel: du fügst die Zahlen 1 bis 7 ein, am Anfang hat das Array die Werte 0 0 0 0 0

1 0 0 0 0
1 2 0 0 0
1 2 3 0 0
1 2 3 4 5
6 2 3 4 5
6 7 3 4 5

Hast du das System verstanden?

Du musst in deiner Anwendung natürlich immer die 5 durch die Anzahl der zu speichernden Elemente ersetzen…

Grüße,
Moritz

1 Like

Hi Alexander,

also, wenn Du nicht mit einem Ringspeicher arbeiten willst, könntest Du die Funktion MoveMemory verwenden. Das sollte dann ziemlich schnell laufen:

// Verschiebt die Werte in pArray um eine Position nach links:
// pArray[0]=pArray[1]
// pArray[1]=pArray[2]
// ...
// pArray[nElementCnt-2]=pArray[nElementCnt-1]
// Aufrufparameter:
// pArray =\> Array mit den Werten
// nElementCnt =\> Anzahl Werte im Array
void ShiftLeft(double \*pArray, INT nElementCnt)
{
 if (nElementCnt\>1)
 MoveMemory(pArray, &pArray[1], (nElementCnt-1) \* sizeof(double) );
}

Gruß
Uwe

Hallo Alexander,

hier ein Beispiel.

Hallo moritz, Dein Verfahren ist zwar gut, läst aber das nutzen Aufeinander folgender Werte nicht zu. Daher hier noch einmal, wie in Deinem Beispiel für 5 WEerte:

#define N (5) // Maximale Anzahl der Elemente im Array

float array[2 \* N]; // das array ist doppelt so lang wie notwendig!

int idx = 0; 

#define current\_array (&array[idx])

void insert\_value(float val)
{
 array[idx] = val;
 array[idx + N] = val; // das ist der clou, 2x einsetzen:wink:
 idx++;
 if(idx \>= N) idx = 0; // ein "wrap around" wenn das Ende erreicht ist
}


void main(void)
{
float neuerWert;

 for(;:wink: // einer oder DER Weg für Endlosschleifen
 {
 int i;
 float dummy;
 ... // neuen Wert bekommen
 insert\_value(neuerWert);
 ... // gleich folgt die Benutzung des Arrays
 dummy = 0;
 for(i = 0; i

Gruß
achim


> <small>[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]</small>

Warum ein Array?
Hi Alexander,

Warum willst du unbedingt ein Array nehmen? Wenn du eh nur sequentiell lesen willst (und wenn ich richtig verstanden habe, den neuesten Wert an erster Stelle ), dann verwende doch eine verkettete Liste aus doubles.
Also etwa so:

#include 
typedef CListCDblList;

CDblList L;
double x;

L.AddHead (x); // einfügen am Anfang der Liste;
L.RemoveTail(); // evtl gleich letztes löschen (od. irgenwann mal 100 auf einmal)

double auslesen (int anzahl) {
 double dbl;
 for (int i=0; i
nicht vergessen, am Programmende die komplette Liste mit L.RemoveAll() zu löschen!

Gruß,
husky

Hallo husky,

Warum willst du unbedingt ein Array nehmen? Wenn du eh nur
sequentiell lesen willst (und wenn ich richtig verstanden
habe, den neuesten Wert an erster Stelle ), dann verwende doch
eine verkettete Liste aus doubles.

Allerdings ging es um die Reduzierung des Rechenaufwandes.
Mit new() erzeugst du jede menge Rechnerei bei der Speicherverwaltung.

Das schnellste ist in jedem Fall der vorgeschlagene Ringbuffer.

MfG Peter(TOO)