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
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
Ist das nicht sowas wie ein Logarithmus? Das hier sollte doch sowas tun:
1 | #define MAXPOW2(x) \
|
2 | (\
|
3 | (x) >= 128? 1:\
|
4 | (\
|
5 | (x) >= 64? 2:\
|
6 | (\
|
7 | (x) >= 32? 4:\
|
8 | (\
|
9 | (x) >= 16? 8:\
|
10 | (\
|
11 | (x) >= 8? 16:\
|
12 | (\
|
13 | (x) >= 4? 32:\
|
14 | (\
|
15 | (x) >= 2? 64: 128\
|
16 | )\
|
17 | )\
|
18 | )\
|
19 | )\
|
20 | )\
|
21 | )\
|
22 | )
|
Die Einrückungen sind nur der Schönheit wegen :), man kann das natürlich auch etwas kompakter schreiben:
1 | #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)))))))
|
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 !
Ich habs mal ausprobiert: Es macht genau das was ich wollte. Nochmals Danke !
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.