Kann man diesen C-Code vereinfachen?

OP Persönliche Seite #5974023
Lesenswert?

Hallo,

ich habe diesen C-Code, und ich wollte mal fragen ob man diesen 
vielleicht in einen einzeiligen oder einfacheren Code vereinfachen kann.
Natürlich in Anbetracht der Tatsache, dass es sinnvoll ist und nicht im 
Assembler die vielfache Größe wird.

Wenn man die Zahlen 1...4 in die Zahlen 1,2,4,8 wandeln möchte, geht das 
ja mit dem Schiebebefehl gut. Aber hier ist es die andere Richtung. Ich 
habe keine bessere Lösung gefunden.
1
   switch (Input) 
2
    {
3
       case 1:  Output = 1;     break;
4
       case 2:  Output = 2;     break;
5
       case 4:  Output = 3;     break;
6
       case 8:  Output = 4;     break;
7
    };
#5974040
Lesenswert?

Ich würde hier auch nichts vereinfachen, falls nicht noch mehr Werte 
benötigt werden. Falls doch, würde ich mit einer i=0..n Schleife auf 
alle Bits testen und mir nur was anderes überlegen, wenn das zu langsam 
ist.

"Leicht verständlich" ist immer wichtiger als "kurz" und fast immer 
wichtiger als "schnell", außer es ist klar, dass genau an dieser Stelle 
"schnell" relevant ist.
Gast #5974091
Lesenswert?

Armin K. schrieb:
> Ich habe keine bessere Lösung gefunden.

Diese Lösung ist für den Leser des Programms die beste Variante.
Sie ist klar verständlich und die Funktion ist auf den ersten Blick 
klar.

Bei einer LUT muss man schon etwas länger nachdenken. Die wäre aber auf 
jeden Fall die bessere Wahl, wenn es sich viele (ich sage mal mehr als 
8) Werte handelt.
Gast #5974095
Lesenswert?

So würde man das mit >> machen

int convert(int val)
{
  int i=1;
  while (val >>= 1)
    i++;
  return i;
}

Aber wie von vielen hier schon gesagt, ist Deine Lösung mit dem 
switch-Statement viel verständlicher. Oder, um es mit einem der Erfinder 
von C zu sagen: Wenn Du beim Schreiben Deines Programms schon 100% 
Deines Könnens verwendest, wie willst Du das Teil dann jemals debuggen?
Gast #5974138
Lesenswert?

Bitte beachte, dass die Lösung mit Lookuptable nicht äquivalent zu 
Deiner Switch-Case-Lösung ist, da diese auch für die 
Zwischen-Eingangswerte gültige Ausgangswerte zurückliefert, aber keine 
Bereichsprüfung des Eingangswerts umfasst und somit z. B. für den 
Eingangswert 9 keinen gültigen Ausgangswert liefert, für den Wert 3 aber 
schon.
Daher müsstest Du zuerst klären, was Du überhaupt erreichen willst, denn 
daraus ergeben sich die möglichen Lösungen.
Moderne Compiler sind nicht doof, so dass dieser ein vollständig 
definiertes Switch-Case-Konstrukt auch selbständig durch eine 
Lookuptable ersetzen kann, wenn alle weiteren Parameter passen, d. h. 
Optimierungsstufe (Du musst dem Compiler sagen, ob er auf 
Geschwindigkeit oder Platzverbrauch optimieren soll; davon hängt die 
beste Lösung ab), Rechnerarchitektur usw.
Am Ende des Tages hilft wohl nur Ausprobieren unter Deinen spezifischen 
Rahmenbedingungen; letztlich sollte die Lösung jedoch primär für 
C-Verständige gut verständlich und nachvollziehbar sein und keine 
"Tricksereien" beinhalten, von denen in zwei Tagen auch Du nicht mehr 
weißt, was Du da genau gemacht hast - wie oben schon steht, wie willst 
Du Deinen Code ordentlich debuggen, wenn Du schon selbst beim Lesen 
Deines eigenen Codes Schwierigkeiten hast und permanent überlegen musst, 
warum Du etwas so gemacht hast und was Du damit eigentlich bezwecken 
wolltest.
Gast #5974156
Lesenswert?

Lass es so wie es ist.

Der Vollständigkeit halber: man kann das, insb für größere Zahlen, durch 
binäre Suche machen, z.B. für 32 Bit:
1
   Ouput = ((Input & 0xffff0000) ? 16 : 0)
2
         + ((Input & 0xff00ff00) ? 8 : 0)
3
         + ((Input & 0xf0f0f0f0) ? 4 : 0)
4
         + ((Input & 0xcccccccc) ? 2 : 0)
5
         + ((Input & 0xaaaaaaaa) ? 1 : 0)
6
         + (Input != 0);
Bei deinem Zahlenbereich (1,2,4,8) wäre es:
1
   Output = ((Input & 0xc) ? 2 : 0)
2
          + ((Input & 0xa) ? 1 : 0)
3
          + 1;
#5974161
Lesenswert?

foobar schrieb:
> Lass es so wie es ist.

Besser wäre es.

>
> Der Vollständigkeit halber: man kann das, insb für größere Zahlen, durch
> binäre Suche machen, z.B. für 32 Bit:
>
1
>    Ouput = ((Input & 0xffff0000) ? 16 : 0)
2
>          + ((Input & 0xff00ff00) ? 8 : 0)
3
>          + ((Input & 0xf0f0f0f0) ? 4 : 0)
4
>          + ((Input & 0xcccccccc) ? 2 : 0)
5
>          + ((Input & 0xaaaaaaaa) ? 1 : 0)
6
>          + (Input != 0);
7
>
> Bei deinem Zahlenbereich (1,2,4,8) wäre es:
>
1
>    Output = ((Input & 0xc) ? 2 : 0)
2
>           + ((Input & 0xa) ? 1 : 0)
3
>           + 1;
4
>

Super lesbar. Auf wie viele WTFs/Sekunde kommst du so in deinen Code 
Reviews?
Gast #5974275
Lesenswert?

Kleiner Schwank am Rande:

Falk B. schrieb:
> 90% der Rechenleistung werden in 10% des Codes verbraucht.

Genau deswegen haben Scriptsprachen (auf Servern) zur Implementierung 
der Geschäftslogik durchaus eine Existenzberechtigung. Die harte Arbeit 
(z.B. XML Parsing) machen fertige Bibliotheken, die in einer effizienten 
Sprache implementiert ist.

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