[C]Alternative für langes "if...else"

Herakles

Profifragensteller
Moin!

Ich möchte eine Variable auf verschiedene Wertbereiche abprüfen. Bisland mache ich das mit if ... else, aber ich denke, dass das sehr unperformant ist. Besser wäre sicher ein switch ... case, aber ich weiß gar nicht, wie ich sowas realisieren könnte.

Hat da jemand eine Idee?

Mein Beispiel sieht etwa so aus:

Code:
if( (mean_drift > 2000) && (mean_drift < 20000) ) {
// mach was
} else if( (mean_drift < 0) && (mean_drift > -20000) ) {
// mach was
} else if( mean_drift >= 20000 ) {
// mach was
} else if( mean_drift <= -20000 ) {
// mach was
}

Ich hoffe, ich konnte beschreiben, was ich erreichen will...

Beste Grüße
Herakles
 
Ich denke das ist so ziehmlich das beste, ohne großen Voodoo zu machen.
sry gerade gesehen das du werte Bereiche vergleichen möchtest.
 
Zuletzt bearbeitet:
Moin!

Ich möchte eine Variable auf verschiedene Wertbereiche abprüfen. Bisland mache ich das mit if ... else, aber ich denke, dass das sehr unperformant ist.

Ich glaube nicht, dass das so in die Performance reinhaut. Was du noch optimieren könntest:

a) Tests, von denen zu erwarten ist, dass Sie oft wahr ergeben, ganz nach oben
b) unnötige Tests elimieren

Rob
 
Besser wäre sicher ein switch ... case, aber ich weiß gar nicht, wie ich sowas realisieren könnte.

switch-Anweisungen können (ab C99) auch Bereiche abdecken. Möglicherweise könnte es also folgendermaßen gehen:
Code:
switch(mean_drift) {
       case 2000 ... 20000 : foo(); break;
       case 20000 ... MAX_VALUE : bar(); break;
       usw...
}
 
Zuletzt bearbeitet:
switch-Anweisungen können auch Bereiche abdecken. Möglicherweise könnte es also folgendermaßen gehen:
Code:
switch(mean_drift) {
       case '2000' ... '20000' : foo(); break;
       case '20000' ... 'MAX_VALUE' : bar(); break;
       usw...
}

Ich denke nicht, dass das in C geht. Nebenbei ist '2000' keine Zahl.

EDIT: geht wohl doch, aber trotzdem dürfen die Zahlen nicht in Hochkommata stehen.

Rob
 
Ich denke, es ist performanter, weil so nicht jeder if-Zweig abgearbeitet wird, sondern immer nur in ein case reingesprungen wird.

Aber mal davon ab: Nun möchte ich ein ">x" oder "<x" haben.

Wie macht man das mit switch/case?

Hab Blut geleckt... :)

Herakles
 
Aber mal davon ab: Nun möchte ich ein ">x" oder "<x" haben.

Wie macht man das mit switch/case?

Mir wäre nicht bekannt, dass das so direkt machbar ist. Je nach Datentyp der zu vergleichenden Variablen würde ich daher eine untere bzw. obere Grenzen setzen und somit wieder einen Bereich abgrenzen. Das war mit MAX_VALUE in meinem Beispiel gemeint.
 
Ich denke, es ist performanter, weil so nicht jeder if-Zweig abgearbeitet wird, sondern immer nur in ein case reingesprungen wird.
Wie stellst du dir das vor? Eine Sprungleiste mit 40.000 Einträgen? Da freut sich die Sprungvorhersage und der Cache.

Offensichtliche Vereinfachung durch Sortieren:
Code:
if (mean_drift <= -20000) {
} else if (mean_drift < 0) { /* off-by-one? */
} else if (mean_drift <= 2000) {
} else if (mean_drift < 20000) { /* off-by-one? */
} else {
}
 
In Maschienencode würde dein if else die Optimale lösung darstellen. Wie das von gcc umgesetzt wird kann ich nicht sagen ich denke aber, das durch Optimierungen das Ganze genau so schlank wird wie selbst in Assembler gebastelt.
Übrigens ist eine case Anweisung nach dem Übersetzen das selbe wie ein if else Konstrukt.
 
Jepp, ath0 sagts.
Hier würde ich switch case nur wegen der Lesbarkeit wählen, weil die Fallentscheidung sofort klar ist.
 
Alternativ kannst Du (angenommen Du hast eine homogene Verteilung) if-else so benutzen, dass Du eine binäre Suche formulierst. Dann hast Du nicht so viele Abfragen.
 
Ist diese Funktion wirklich wichtig für die Performance deines Codes als ganzes? Sonst nimm das leserlichste. Übertreibe es bloß nicht ohne zu benchmarken auf deinen Zielsystemen. Das ganze hängt hier von der Sprungvorhersage, dem Scheduling der Instruktionen durch den Compiler und die CPU ab. Nichts davon wird die nächsten 3 Jahre gleich bleiben, wenn du für Desktopsysteme kompilierst. Ein schönes Negativbeispiel wäre die lange Zeit auf Netbrust optimierte AES Implementierung in OpenSSL (etwas über 4kB L1D Cache pro aufbereitetem Schlüssel, geringe Ausnutzung von super-skalarer Ausführung, keine SIMD Befehle genutzt).
 
Zurück
Oben