Wenn ich eine ganzzahlige Zahl habe n
, wie kann ich die nächste Zahl k > n
so finden, dass k = 2^i
mit einem i
Element von N
durch bitweise Verschiebung oder Logik.
Beispiel: Wenn n = 123
ja, wie kann ich herausfinden k = 128
, welche Zweierpotenz ist und welche nicht 124
nur durch zwei teilbar ist? Das sollte einfach sein, aber es entgeht mir.
language-agnostic
bit-manipulation
AndreasT
quelle
quelle
Antworten:
Für 32-Bit-Ganzzahlen ist dies eine einfache und unkomplizierte Route:
Hier ist ein konkreteres Beispiel. Nehmen wir die Zahl 221, die binär 11011101 ist:
Es gibt ein Bit an der neunten Position, das 2 ^ 8 oder 256 darstellt, was in der Tat die nächstgrößere Potenz von 2 ist . Jede der Verschiebungen überlappt alle vorhandenen 1 Bits in der Zahl mit einigen der zuvor unberührten Nullen, wodurch schließlich eine Anzahl von 1 Bits erzeugt wird, die der Anzahl der Bits in der ursprünglichen Zahl entspricht. Das Hinzufügen von eins zu diesem Wert ergibt eine neue Potenz von 2.
Ein anderes Beispiel; Wir werden 131 verwenden, was 10000011 in binär ist:
Und tatsächlich ist 256 die nächsthöhere Potenz von 2 von 131.
Wenn die Anzahl der zur Darstellung der Ganzzahl verwendeten Bits selbst eine Zweierpotenz ist, können Sie diese Technik weiterhin effizient und unbegrenzt erweitern (z. B. eine
n >> 32
Zeile für 64-Bit-Ganzzahlen hinzufügen ).quelle
k >= n
nichtk > n
Hierfür gibt es tatsächlich eine Montagelösung (seit dem 80386-Befehlssatz).
Mit der Anweisung BSR (Bit Scan Reverse) können Sie nach dem höchstwertigen Bit in Ihrer Ganzzahl suchen.
(Auszug aus: http://dlc.sun.com/pdf/802-1948/802-1948.pdf )
Und dann inc das Ergebnis mit 1.
damit:
In neueren CPUs können Sie die viel schnellere
lzcnt
Anweisung (auch bekannt alsrep bsr
) verwenden.lzcnt
erledigt seine Arbeit in einem einzigen Zyklus.quelle
Ein mathematischerer Weg ohne Schleifen:
quelle
2 ^ (floor(log(x) / log(2)) + 1)
n
es sich um eine Zweierpotenz handelt und Sien
anstelle der "nächsten Zweierpotenz" erhalten möchten , können Sie2 ^ ( ceil(log(x) / log(2)) )
stattdessen verwenden. Aber das war nicht die Frage (… wie kann ich die nächste Nummer findenk > n
…)Hier ist eine logische Antwort:
quelle
Hier ist John Feminellas Antwort, die als Schleife implementiert ist, damit sie Pythons lange ganze Zahlen verarbeiten kann :
def next_power_of_2(n): """ Return next power of 2 greater than or equal to n """ n -= 1 # greater than OR EQUAL TO n shift = 1 while (n+1) & n: # n+1 is not a power of 2 yet n |= n >> shift shift <<= 1 return n + 1
Es kehrt auch schneller zurück, wenn n bereits eine Potenz von 2 ist.
Für Python> 2.7 ist dies für die meisten N einfacher und schneller:
def next_power_of_2(n): """ Return next power of 2 greater than or equal to n """ return 2**(n-1).bit_length()
quelle
shift <<= 1
anstelle von tunshift *= 2
. Ich bin mir nicht sicher, ob das in Python tatsächlich schneller ist, sollte es aber sein.Größer als / Größer als oder gleich
Die folgenden Ausschnitte sind für die nächste Zahl k> n, so dass k = 2 ^ i
(n = 123 => k = 128, n = 128 => k = 256), wie durch OP angegeben.
Wenn Sie möchten, dass die kleinste Potenz von 2 größer als OR gleich n ist, ersetzen Sie sie einfach
__builtin_clzll(n)
durch__builtin_clzll(n-1)
die obigen Schnipsel.C ++ 11 mit GCC oder Clang (64 Bit)
Verbesserung mit
CHAR_BIT
wie von martinec vorgeschlagenC ++ 17 mit GCC oder Clang (von 8 bis 128 Bit)
Andere Compiler
Wenn Sie einen anderen Compiler als GCC oder Clang verwenden, besuchen Sie bitte die Wikipedia-Seite, auf der die bitweisen Funktionen von Count Leading Zeroes aufgeführt sind :
__builtin_clzl()
durch_BitScanForward()
__builtin_clzl()
durch__lzcnt()
__builtin_clzl()
durch_bit_scan_forward
__builtin_clzl()
durchcountLeadingZeros()
Beitrag willkommen
Bitte schlagen Sie Verbesserungen in den Kommentaren vor. Schlagen Sie auch eine Alternative für den von Ihnen verwendeten Compiler oder Ihre Programmiersprache vor ...
Siehe auch ähnliche Antworten
quelle
Hier ist eine wilde, die keine Schleifen hat, aber einen Zwischen-Float verwendet.
Dieser und viele andere Hacks, einschließlich der von John Feminella eingereichten, finden Sie hier .
quelle
Angenommen, x ist nicht negativ.
quelle
Wenn Sie GCC, MinGW oder Clang verwenden:
Wenn Sie Microsoft Visual C ++ verwenden, verwenden Sie die Funktion
_BitScanForward()
zum Ersetzen__builtin_clz()
.quelle
constexpr uint64_t nextPowerOfTwo64 (uint64_t x) { return 1ULL << (sizeof(uint64_t) * 8 - __builtin_clzll(x)); }
quelle
Bit-Twiddling, sagst du?
Jede Schleife entfernt das niedrigstwertige 1-Bit direkt. NB Dies funktioniert nur, wenn vorzeichenbehaftete Nummern im Zweierkomplement codiert sind.
quelle
while
mitdo/while
und speichert einen Test, wie Sie bereits den ersten Test mit der vorhergehenden bestätigtenif
Aussage.do while
.while(t > (t & -t))
.Was ist mit so etwas:
quelle
Sie müssen nur das höchstwertige Bit finden und es einmal nach links verschieben. Hier ist eine Python-Implementierung. Ich denke, x86 hat eine Anweisung, um das MSB zu erhalten, aber hier implementiere ich alles in reinem Python. Sobald Sie das MSB haben, ist es einfach.
quelle
Vergiss das! Es verwendet Schleife!
quelle
quelle
quelle
n+min+1
?oder auch
quelle