www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C: "rollierender Index" in Array möglichst elegant realisieren?


Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

folgendes Code-Beispiel:
int MyArray[100] = {1,2, ..., 100};

for(int i=-200; i<=200; i++)
{
  int var = MyArray[i%(sizeof(MyArray)/sizeof(int))];
}

MyArray sei ein abgeschlossener Wertebereich ... d.h MyArray[99+1] wird 
wieder zu MyArray[0] vergleichbar z.B. mit Sinus von 0 bis 2PI.

Durch die modulo-Operation erreiche ich ja, dass alle Werte >99 wieder 
heruntergebrochen werden und so in den Wertebereich von MyArray passen.

Jetzt die Frage: Gibt es auch ein hübsches kleines Konstrukt OHNE 
if/else mit dem ich dasselbe für Werte <0 erreiche? Also quasi 
MyArray[-1] wird zu MyArray[99]. D.h. am Schluss sollte sowas stehen 
wie:
  int var = MyArray[i<this_is_where_the_magic_happens>];

welches den Wertebereich nach oben und unten automatisch "klammert". 
Gibt's da was?

Vielen Dank im Voraus.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(peda)
#define ROLLOVER( x, max )  x = ++x >= max ? 0 : x


WIrd aber vom Compiler sicher in ein if-konstrukt umgewandelt

Autor: icke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
myArry[nextpos++] = xyz;
nextpos &= SIZE - 1;

Wenn SIZE damit klar kommt, eine Zweierpotenz zu sein, sonst kann man 
auch natürlich nextpos = nextpos % SIZE schreiben.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einfache, spontane Idee :
Was wäre denn, wenn du vor der modulo Operation einfach 100 ( die Größe 
deines Array) addierst ?
Dann würde aus deiner -1 eine 99 werden und somit hättest du den 
gleichen Effekt für Zahlen, die <0 sind.

Gruß
Stefan

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lippy und icke:

Ich glaube, eure Vorschläge funktionieren nicht für die geforderten 
negativen Zahlen.

@Alex Wurst:

Mir fällt nix ein, was ohne Fallunterscheidung (if/else oder ?-Operator) 
auskommt. Je nach Zielplattform könnte aber die Unterscheidung 
performanter sein als die Division.

Gruß,
Tuppes

Autor: I_ H. (i_h)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du dich auf einen bestimmten Wertebereich festlegst (du brauchst ja 
wahrscheinlich keine 2^32 Arrayeinträge) kannst du zB. die Untergrenze 
(die dem Element 0 entsprechen sollte) draufaddieren.

Also Arraygröße 10, Untergrenze -100 -> vor der Rechnung 100 
draufaddieren, dann Modulo.

So richtig schön sauber ist das aber auch nicht, wegen der Einschränkung 
im Wertebereich. Aber 30 oder gar 31 Bits sollten sich damit noch 
realisieren lassen.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich glaube, eure Vorschläge funktionieren nicht für die geforderten
>negativen Zahlen.

Negative Array-Indizes haben ja auch keinen Sinn!

Autor: icke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube bei erneutem durchlesen verstehe ich gar nciht mehr so ganz 
genau worum es geht.
Dachte bei rollierend an einen klassischen Ringpuffer, aber scheint ja 
so zu sein, daß man nicht inkrementiert in das Array geht. Das verändert 
des Offsets sich also schenken kann.

Da bleibt einem dann außer einem modulo vor dem Zugriff und wegen mir 
verschieben des index zu Null eigentlich nichts übrig oder sehe ich das 
falsch?

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
array[index & MASK]

Autor: ●● pit ●● (pit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hello,

ohne deinen restlichen 'Geheimalgorithmus' kann man ohnehin
nix bzw. nur kontextfrei optimieren.

Aber man kann eventuell einfach den Nummernbereich des Array-Index
verschieben, so das es keine negativen mehr gibt und den Also
entspr. anpassen. (i.e. 0 > 400 statt -200 > +200)

Möglicherweise klappt auch ein mehrdimensionales Array, i.e.:
int arr[2][100] = {
     { 1,2,   ..., 100},
     { -1,-2, ..., -100}
};

for(...)
{
  int pos = arr[0][i%size)];
  int neg = arr[1][i%size)];
}

Ist deine Anforderung eigentlich rein ästhetischer Natur, oder gibt
es auch einen praktischen Grund wie z.B. Code Size oder Performance?
(Man soll ja nur optimieren, wenn es wirklich nötig ist oder was bringt 
und nicht die Lesbarkeit verschlechtert.)

hth,
 - Karl

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex Wurst wrote:

>
> int MyArray[100] = {1,2, ..., 100};
> 
> for(int i=-200; i<=200; i++)
> {
>   int var = MyArray[i%(sizeof(MyArray)/sizeof(int))];
> }
> 

Was soll das bringen, in einer Schleife immer wieder die gleiche 
Rechnung zu machen, soll das ne Delay-Schleife werden?

Insbesondere die (Modulo-)Division schlägt auf MCs ohne Division so 
richtig ein.

Nimm einfach ne 2. Variable und setze sie auf 0, wenn >=99 und gut is.

Oder nimm nen Pointer und setze ihn auf Array-Start, wenn >Array-End.


Peter

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  ... möglichst elegant realisieren?

Was ist das und warum?

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht nach wie vor um einen Ringpuffer, bei dem z.B. MyArray[-10] 
interpretiert wird als MyArray[Max-10].

Ich habe hier gerade ein ziemliches Gewurschtel an if/else-Konstrukten, 
bei dem ich Werte in einem Array nachbearbeite... Kritisch sind hierbei 
die Randbereiche des Arrays: Angenommen ich habe einen Filter, der die 
Werte n-2 bis n+2 benötigt, wobei n = zu berechnende Position im Array 
von 0 ... 99 ist, dann würde ich z.B. für Position MyArray[0] die 
folgenden Indexe benötigen:

 [98],  [99], [0],  [1],    [2]
(n-2), (n-1), (n), (n+1), (n+2)

und da Wäre ein kleines (evtl auch Makro)-Konstrukt schön, weil ich mir 
2-3 verschachtelte Wertebereich-IFs sparen könnte.

Alles klar?

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn sizeof(Myarray) eine Zweierpotenz ist, sollte doch eine Maskierung 
auf die entsprechenden Bits reichen?

Mit ein paar Casts sollte das auch für negative Zahlen machbar sein
(da normal (int16)(-1) = (uint16)65535 )

@Alex Wurst
Was spricht dagegen eine 2er -Potenz zu verwenden. Dann kannst du's 
machen wie von Random... vorgeschlagen.

ansonsten würde ich es evtl so machen:
array[ ((idx % size) + size) % size]
kommt mit negativen Zahlen klar und es kommt kein Vergleich drin vor.
(auf einen µC der absolute Performance-Killer, auf nen x86 aber ggf. 
schneller als mit IF-Abfrage, da die Pipeline nicht unterbrochen wird)

Gruß
Roland

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Code läuft auf nem x86 und kann wenn's sein muß auch 3 Tage 
laufen... der µC wird später nur mit dem Ergebnis zu Simulationszwecken 
gefüttert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.