Wie prüft diese bitweise Operation auf eine Potenz von 2?

Lesezeit: 5 Minuten

Ich schaue mir einen Code an, der trivial sein sollte – aber meine Mathematik versagt hier kläglich.

Hier ist eine Bedingung, die überprüft, ob eine Zahl eine Potenz von 2 ist, indem Folgendes verwendet wird:

if((num != 1) && (num & (num - 1))) { /* make num pow of 2 */ }

Meine Frage ist, wie bestimmt die Verwendung eines bitweisen AND zwischen num und num – 1, ob eine Zahl eine Potenz von 2 ist?

  • Weitere Informationen finden Sie unter dieser Frage: stackoverflow.com/questions/600293/…

    – Greg Hewgill

    27. Juni 2009 um 23:38 Uhr

  • Es kommt natürlich auf die Art an num – Die meisten Antworten hier gehen davon aus, dass es sich um einen ganzzahligen Typ ohne Vorzeichen handelt, bei dem die bitweisen Operationen genau definiert sind.

    – Toby Speight

    5. April 2017 um 14:39 Uhr

Benutzeravatar von eduffy
eduffy

Jede Potenz von 2 minus 1 ist alles Einsen: (2 N – 1 = 111….b)

2 = 2^1.  2-1 = 1 (1b)
4 = 2^2.  4-1 = 3 (11b)
8 = 2^3.  8-1 = 7 (111b)

Nehmen Sie zum Beispiel 8. 1000 & 0111 = 0000

Dieser Ausdruck testet also, ob eine Zahl KEINE Potenz von 2 ist.

  • Eckfall, wenn 1.num=0 und num = -2147483648, wenn der Datentyp int ist und durch den Mindestwert begrenzt ist. Wenn num==0 ist, ist num keine Zweierpotenz

    – Bhaskar13

    14. August 2020 um 18:53 Uhr


  • Wie beweist diese Erklärung etwas? Es zeigt lediglich, dass eine Potenz von 2 produzieren würde 0 für den Ausdruck x & (x - 1)nicht umgekehrt.

    – chqrlie

    19. Februar um 15:17 Uhr

Benutzeravatar von lavinio
lavinio

Nun, der erste Fall prüft auf 20 == 1.

Für die anderen Fälle die num & (num - 1) kommt ins Spiel:

Das heißt, wenn Sie eine beliebige Zahl nehmen und die Bits von einer niedrigeren maskieren, erhalten Sie einen von zwei Fällen:

  1. Wenn die Zahl bereits eine Zweierpotenz ist, führt eine Zahl weniger zu einer Binärzahl, bei der nur die niederwertigen Bits gesetzt sind. Verwenden & es wird nichts tun.

    • Beispiel mit 8: 0100 & (0100 - 1) –> (0100 & 0011) –> 0000
  2. Wenn die Zahl nicht bereits eine Zweierpotenz ist, berührt eins weniger nicht das höchste Bit, also wird das Ergebnis sein wenigstens die größte Zweierpotenz kleiner als num.

    • Beispiel mit 3: 0011 & (0011 - 1) –> (0011 & 0010) –> 0010

    • Beispiel mit 13: 1101 & (1101 - 1) –> (1101 & 1100) –> 1100

Der tatsächliche Ausdruck findet also alles, was keine Zweierpotenz ist, einschließlich 20.

  • Eigentlich die Prüfung für den Spezialfall num==1 (2^0=1) wird nicht benötigt. Für diesen Fall ist (num & (num-1)) = (1 & 0) = 0 sowieso.

    – farindk

    8. Mai 2014 um 14:18 Uhr

  • Die Erklärung des zweiten Punktes ist falsch, (num – 1) könnte eine Zweierpotenz sein, muss es aber nicht. Der Grund, warum das Ergebnis immer ungleich Null ist, liegt darin, dass die Operation dies kann stets übertragen werden, ohne das höchste Bit zu berühren, und zumindest dieses Bit wird in der Ausgabe angezeigt.

    – Ismael Luceno

    18. Dezember 2014 um 20:53 Uhr

  • Der Kommentar von Ismael Luceno ist eine bessere Erklärung für diese Beobachtung

    – Ketcomp

    23. Juli 2016 um 18:17 Uhr

  • Wie in den Kommentaren oben erwähnt, ist die Aussage in Punkt 2: “die die höchste Potenz von 2 nicht größer als num zurückgibt”, falsch. Es sollte genauer lauten “was zurückkehrt wenigstens die höchste Potenz von 2 nicht größer als num”. Ich habe diese Antwort bearbeitet und wartet auf die Begutachtung durch Kollegen.

    – xdavidliu

    5. Juli 2018 um 0:05 Uhr

Benutzeravatar von Toon Krijthe
Toon Krijthe

Brunnen,

Wenn Sie X = 1000 haben, dann ist x-1 = 0111. Und 1000 && 0111 ist 0000.

Jede Zahl X, die eine Potenz von 2 ist, hat eine x-1, die Einsen an der Stelle hat, an der x Nullen hat. Und ein bitweises und von 0 und 1 ist immer 0.

Wenn die Zahl x keine Zweierpotenz ist, zum Beispiel 0110. Das x-1 ist 0101 und das und ergibt 0100.

Für alle Kombinationen innerhalb von 0000 – 1111 führt dies zu

   X  X-1 X && X-1  
0000 1111 0000   
0001 0000 0000 
0010 0001 0000
0011 0010 0010
0100 0011 0000
0101 0100 0100
0110 0101 0100
0111 0110 0110
1000 0111 0000
1001 1000 1000
1010 1001 1000
1011 1010 1010
1100 1011 1000
1101 1100 1100
1110 1101 1100
1111 1110 1110

Und es bedarf keiner gesonderten Prüfung für 1.

  • Aber natürlich muss auf 0 geprüft werden, da 0 keine Potenz von 2 ist, aber es wird getestet, als ob es eine wäre.

    – Steve Jessop

    27. Juni 2009 um 21:58 Uhr

  • Ein paar Dinge hier – zuerst denke ich, dass Sie verwenden && ein paar Stellen, wo Sie meinten &. n && (n-1) wäre fast überall 1 (außer für n = 0 und n = 1, richtig?) Zweitens ist 1 eine Potenz von 2, aber das “Bedürfnis” hängt vom Kontext ab, den wir nie gesehen haben (“wahr, wenn die Macht positiv / natürlich ist” , oder umgekehrt „wahr, wenn genau ein Bit gesetzt ist“ usw.) Nichts Persönliches, das war sowieso fast ein Jahrzehnt her.

    – Johannes P

    19. Februar 2018 um 11:56 Uhr

Ich bevorzuge diesen Ansatz, der auf dem Zweierkomplement beruht:

bool checkPowTwo(int x){
    return (x & -x) == x;
}

Benutzeravatar von rohittt
Rohittt

Erklärt hier schön

Auch der angegebene Ausdruck betrachtet 0 als Potenz von 2. Um dies zu beheben, verwenden Sie
!(x & (x - 1)) && x; stattdessen.

  • Nein das ist falsch. Es gibt kein x mit 2**x = 0. Also ist x keine Potenz von 2.

    – Accipitridae

    28. Juni 2009 um 13:29 Uhr

Benutzeravatar von Toby Speight
Toby Speight

Es bestimmt, ob Integer eine Potenz von 2 ist oder nicht. Wenn (x & (x-1)) Null ist, dann ist die Zahl eine Potenz von 2.

Lassen Sie zum Beispiel x 8 sein (1000 in binär); dann x-1 = 7 (0111).

if    1000
  &   0111
---------------
      0000

C-Programm zur Demonstration:

#include <stdio.h>

void main()
{
    int a = 8;
    if ((a&(a-1))==0)
    {
        printf("the bit is power of 2  \n");
    }
    else 
    {
        printf("the bit is not power of 2\n");
    }
}

Dies gibt aus the bit is power of 2.

#include <stdio.h>

void main()
{
    int a = 7;
    if ((a&(a-1))==0)
    {
        printf("the bit is power of 2  \n");
    }
    else 
    {
        printf("the bit is not power of 2\n");
    }
}

Dies gibt aus the bit is not power of 2.

  • Nein das ist falsch. Es gibt kein x mit 2**x = 0. Also ist x keine Potenz von 2.

    – Accipitridae

    28. Juni 2009 um 13:29 Uhr

Benutzeravatar von Shobhit Srivastava
Shobhit Srivastava

Angenommen, n ist die gegebene Zahl,
wenn n eine Potenz von 2 ist (n && !(n & (n-1)) gibt 1 zurück, sonst 0

1413440cookie-checkWie prüft diese bitweise Operation auf eine Potenz von 2?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy