C: "rollierender Index" in Array möglichst elegant realisieren?

#955493
Lesenswert?

Hallo,

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

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

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:
1
  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.
Gast #955535
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
Gast #955552
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
#955565
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.
Gast #955599
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?
Gast #955601
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.:
1
int arr[2][100] = {
2
     { 1,2,   ..., 100},
3
     { -1,-2, ..., -100}
4
};
5

6
for(...)
7
{
8
  int pos = arr[0][i%size)];
9
  int neg = arr[1][i%size)];
10
}

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
#955617
Lesenswert?

Alex Wurst wrote:

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

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
#955627
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?
#955650
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:
1
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren