www.mikrocontroller.net

Forum: Compiler & IDEs Berechnungen beim compilieren


Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche ein Makro zu schreiben, das eine Variable in Abhängigkeit 
von einer Konstanten mit einer 2er Potenz multiplizieren soll, so dass 
es keinen Überlauf gibt.
Hier ein paar Beispiele die verdeutlichen was ich machen möchte:
y=pmul(x,13);
x soll hier mit 13*16=208 multipliziert werden, denn 16 ist die größte 
2er Potenz, die sicherstellt, dass das Ergebnis nicht größer als 65535 
werden kann (x=8bit, y=16bit).
y=pmul(x,68);
x soll nun mit 2*68=136 multipliziert werden, denn 2 ist die größte 2er 
Potenz, die sicherstellt, dass das Ergebnis nicht größer als 65535 
werden kann.

In einer Funktion wäre das ganze kein Problem, allerdings kann dann der 
konstante Faktor dann nicht mehr zur Laufzeit berechnet werden. Da der 
Faktor aber auch ein Fließkommazahl sein kann, möchte ich das gerne 
vermeiden.

Ich suche also einen Trick, um zur Compilezeit 255/n zu berechnen und 
das Ergebnis auf eine 2er Potenz abzurunden

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du genügend Speicher hast: Lookup-Table mit 255 Einträgen.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs ja nicht ganz kapiert, was du willst, aber wenn mir bei so 
etwas gar nichts mehr einfällt, und n zur Compilezeit feststeht, dann 
geife ich gerne mal zu Excel, und bau mir eine Tabelle der Art:
(wer will schon Schönheitspreise für das eleganteste Programm...)

#define pmul_1(x) ((65536/2)*(x))
#define pmul_2(x) ((65536/2)*(x))
#define pmul_3(x) ((65535/4)*(x))
...
#define pmul_255(x) ((((65535/256)*(x))

das in eine Headerdatei kopiert, und dann im Programm als

y = pmul_13(x);

aufgerufen. Vielleicht müssen da noch ein paar typecasts rein, aber 
prinzipiell müsste es doch so gehen, oder?

Oliver

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das nicht sowas wie ein Logarithmus?

Das hier sollte doch sowas tun:
#define MAXPOW2(x) \
  (\
  (x) >= 128? 1:\
    (\
    (x) >= 64? 2:\
      (\
      (x) >= 32? 4:\
        (\
        (x) >= 16? 8:\
          (\
          (x) >= 8? 16:\
            (\
            (x) >= 4? 32:\
              (\
              (x) >= 2? 64: 128\
              )\
            )\
          )\
        )\
      )\
    )\
  )

Die Einrückungen sind nur der Schönheit wegen :), man kann das
natürlich auch etwas kompakter schreiben:
#define MAXPOW2(x) ((x)>=128?1:((x)>=64?2:((x)>=32?4:((x)>=16?8:((x)>=8?16:((x)>=4?32:((x)>=2?64:128)))))))

  

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ganz so einfach ist es leider nicht, da die Konstante eine beliebige 
Kommazahl zwischen 0 und 65536 sein kann. Lookup Tabelle o.ä. fallen 
also weg.
Da es bei diesem Zahlenbereich nur 15 Möglichkeiten gibt, könnte ja 15 
verschiedene Funktionen machen, also

#define pmul_1(x, n) ((x)*((n)*1)
#define pmul_2(x, n) ((x)*((n)*2)
#define pmul_4(x, n) ((x)*((n)*4)
#define pmul_8(x, n) ((x)*((n)*8)
#define pmul_16(x, n) ((x)*((n)*16)
#define pmul_32(x, n) ((x)*((n)*32)
#define pmul_64(x, n) ((x)*((n)*64)
...
#define pmul_32768(x, n) ((x)*((n)*32768)

Was ich suche ist, wie ich #if #elif #endif in einem Makro anwende.

Wenn ich also im Programm pmul(x, 5) schreibe, soll das Programm 
pmul_32(x, 5) ausführen, also x*160 berechnen.

#if (n<2)
 pmul_128(x,n)
#elif (n<4)
 pmul_164(x,n)
#elif (n<8)
 pmul_132(x,n)
#elif (n<16)
 pmul_132(x,n)
...
#else
 pmul_11(x,n)
#endif


Mist, zu lange geschrieben, Jörg war schneller.
Ich denke mal das ist genau das was ich suche. Ich werde es mal 
ausprobieren, schonmal Danke !

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs mal ausprobiert: Es macht genau das was ich wollte. Nochmals 
Danke !

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.