Forum: Compiler & IDEs log2() mit Preprocessor


von markus w. (Gast)


Lesenswert?

Es gibt ja für fast alles irgendwelche klugen Makros.
Gibt es ein Makro was den Logarithmus zur Basis 2 einer zahl zurückgibt?
Genauer: die aufgerundete Anzahl an Bits die nötig ist, um eine Zahl zu 
speichern.

Beispiele:
BITSIZE(10) = 4
BITSIZE(255) = 8
BITSIZE(1100) = 11

Ist sowas möglich? Wie würde BITSIZE() aussehen?

von (prx) A. K. (prx)


Lesenswert?

Beispiel für 8 Bits. Ist aber nur bei Konstanten sinnvoll. Je nach 
Prozessor und Compiler gehts auch anders.
1
#define BITSIZE(n) ((n) >= 128 ? 8 \
2
                  : (n) >=  64 ? 7 \
3
                  : (n) >=  32 ? 6 \
4
                  : (n) >=  16 ? 5 \
5
                  : (n) >=   8 ? 4 \
6
                  : (n) >=   4 ? 3 \
7
                  : (n) >=   2 ? 2 \
8
                  : 1)

: Bearbeitet durch User
von Torsten (Gast)


Lesenswert?

Wenn es auch C++ sein darf (kein Makro):
1
template < unsigned N >
2
struct log2
3
{
4
    enum { result = 1 + log2< N / 2 >::result };
5
};
6
7
template <>
8
struct log2< 1 >
9
{
10
    enum { result = 0 };
11
};
12
13
#include <iostream>
14
15
int main()
16
{
17
    std::cout << "log2(1)" << log2<1>::result << std::endl;
18
    std::cout << "log2(4)" << log2<4>::result << std::endl;
19
    std::cout << "log2(1024)" << log2<1024>::result << std::endl;
20
}

mfg Torsten

von (prx) A. K. (prx)


Lesenswert?

Wenn n nicht immer konstant ist empfiehlt sich bei GCC etwas wie dies, 
weil dann je nach Prozessor auf entsprechenden Befehl abgebildet:
1
#define BITSIZE(n) (32 - __builtin_clz((uint32_t)(n)))

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

A. K. schrieb:
> Wenn n nicht immer konstant ist empfiehlt sich bei GCC etwas wie dies,
> weil dann je nach Prozessor auf entsprechenden Befehl abgebildet:
>
1
#define BITSIZE(n) (32 - __builtin_clz((uint32_t)(n)))

Der Cast ist überflüssig; __builtin_clz nimmt nen int:
1
#define BITSIZE(n) (8 * sizeof (int) - __builtin_clz ((n)))
oder eben
1
#define BITSIZE(n) (8 * sizeof (long) - __builtin_clzl ((long)(n)))

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:
> __builtin_clz nimmt nen int:

Eher unsigned. Und es ist nicht nur der Cast Unsinn, sondern auch die 32 
falsch. Korrekt wäre wohl:
1
#include <limits.h>
2
#define BITSIZE(n) (CHAR_BIT * sizeof(unsigned) - __builtin_clz((n)))

: Bearbeitet durch User
von markus w. (Gast)


Lesenswert?

Ich war wohl etwas ungenau:
Es sollte C sein und ich verwende nur Konstante Werte, damit der 
Ausdruck zur Compilezeit konstant ist.
Damit dürfte hoffentlich A.K.s erste Antwort passen.

Danke dafür!

von Beee (Gast)


Lesenswert?

Es gibt noch eine nette Implementierung auf Stackoverflow, die auch 
32Bit verarbeiten kann:

"macro to compute number of bits needed to store a number n"
http://stackoverflow.com/questions/6834868/macro-to-compute-number-of-bits-needed-to-store-a-number-n

1
#define NBITS2(n) ((n&2)?1:0)
2
#define NBITS4(n) ((n&(0xC))?(2+NBITS2(n>>2)):(NBITS2(n)))
3
#define NBITS8(n) ((n&0xF0)?(4+NBITS4(n>>4)):(NBITS4(n)))
4
#define NBITS16(n) ((n&0xFF00)?(8+NBITS8(n>>8)):(NBITS8(n)))
5
#define NBITS32(n) ((n&0xFFFF0000)?(16+NBITS16(n>>16)):(NBITS16(n)))
6
#define NBITS(n) (n==0?0:NBITS32(n)+1)

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
Noch kein Account? Hier anmelden.