Was bedeutet dieser boolesche Wert "(Zahl & 1) == 0"?

79

Auf CodeReview habe ich einen funktionierenden Code gepostet und um Tipps gebeten, um ihn zu verbessern. Eine, die ich bekam, war die Verwendung einer booleschen Methode, um zu überprüfen, ob eine ArrayList eine gerade Anzahl von Indizes hatte (was erforderlich war). Dies war der Code, der vorgeschlagen wurde:

private static boolean isEven(int number)
{
    return (number & 1) == 0;
}

Da ich diesen bestimmten Benutzer bereits für viel Hilfe belästigt habe, habe ich beschlossen, dass es Zeit ist, die SO-Community zu belästigen! Ich verstehe nicht wirklich, wie das funktioniert. Die Methode wird aufgerufen und nimmt die Größe der ArrayList als Parameter (dh ArrayList hat zehn Elemente, Nummer = 10).

Ich weiß, dass eine einzelne &den Vergleich von Nummer und 1 durchführt, aber danach habe ich mich verlaufen.

So wie ich es lese, heißt es return true, wenn number == 0und 1 == 0. Ich weiß, dass das erste nicht stimmt und das letztere offensichtlich keinen Sinn ergibt. Könnte mir jemand helfen?

Bearbeiten: Ich sollte wahrscheinlich hinzufügen, dass der Code funktioniert, falls sich jemand wundert.

Andrew Martin
quelle
2
Weiß jemand, wer dies mit diesem anderen Beitrag verknüpft hat (was nichts mit diesem Zeug zu tun hat)? Kann ich es irgendwie entfernen?
Andrew Martin
1
Verdammt, das ist wirklich schlau!
Cauon
2
Dies wurde auf Twitter vorgestellt.
Jonathon Reinhart
1
@GrijeshChauhan Könnten Sie bitte näher erläutern, wie das schneller geht als number % 2 == 0?
Vrushank

Antworten:

114

Beachten Sie, dass "&" eine bitweise Operation ist. Sie sind sich dessen wahrscheinlich bewusst, aber es ist mir aufgrund der Art und Weise, wie Sie die Frage gestellt haben, nicht ganz klar.

Die theoretische Idee ist jedoch, dass Sie ein int haben, das durch eine Reihe von Einsen und Nullen in Bits ausgedrückt werden kann. Zum Beispiel:

...10110110

In binär, weil es Basis 2 ist, ist es gerade, wenn die bitweise Version der Zahl mit 0 endet, gerade und wenn sie mit 1 endet, ist sie ungerade.

Daher ist ein bitweises & mit 1 für das Obige:

...10110110 & ...00000001

Dies ist natürlich 0, Sie können also sagen, dass die ursprüngliche Eingabe gerade war.

Alternativ können Sie eine ungerade Zahl berücksichtigen. Fügen Sie zum Beispiel 1 zu dem hinzu, was wir oben hatten. Dann

...10110111 & ...00000001

Ist gleich 1 und daher ungleich Null. Voila.

Kirby
quelle
13
Danke - Ihre Erklärung macht es sehr deutlich. Plus jede Antwort, die in einem Voila endet, verdient eine positive Bewertung.
Andrew Martin
1
Sollte wahrscheinlich auch negative Zahlen in dieser Antwort kennen.
Alvin Wong
3
Außerdem würde ich diese Antwort möglicherweise dahingehend ändern, dass sie das Faktoid n%k == n&(k-1)für alle enthält, kdie eine positive Potenz von 2 haben. Es ist möglicherweise nicht das, was der Fragesteller gefragt hat, aber es ist praktisch zu wissen.
flauschig
1
@fluffy sagt nicht, dass es nicht funktionieren würde, aber nicht jeder kennt die Ergänzung von zwei.
Alvin Wong
1
@fluffy sollte es keinen logoder 2^irgendwo in diesem Ausdruck geben?
Navin
67

Sie können die Zahl durch das letzte Bit in der Binärdarstellung entweder gerade oder ungerade bestimmen :

1 -> 00000000000000000000000000000001 (odd)
2 -> 00000000000000000000000000000010 (even)
3 -> 00000000000000000000000000000011 (odd)
4 -> 00000000000000000000000000000100 (even)
5 -> 00000000000000000000000000000101 (odd)
6 -> 00000000000000000000000000000110 (even)
7 -> 00000000000000000000000000000111 (odd)
8 -> 00000000000000000000000000001000 (even)

& zwischen zwei ganzen Zahlen ist bitweiser UND-Operator:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Also, wenn (number & 1) == 0ist true, bedeutet dies numbersogar.


Nehmen wir number == 6dann an:

6 -> 00000000000000000000000000000110 (even)

     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

1 -> 00000000000000000000000000000001

-------------------------------------

0 -> 00000000000000000000000000000000

und wann number == 7:

7 -> 00000000000000000000000000000111 (odd)

     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

1 -> 00000000000000000000000000000001

-------------------------------------

1 -> 00000000000000000000000000000001
Eng.Fouad
quelle
18

&ist der bitweise AND-Operator. &&ist der logische UND-Operator

Wenn im Binärmodus das Ziffernbit gesetzt ist (dh eins), ist die Zahl ungerade.

Wenn im Binärformat das Ziffernbit Null ist, ist die Zahl gerade.

(number & 1) ist ein bitweiser UND-Test des Ziffernbits.

Eine andere Möglichkeit (und möglicherweise weniger effizient, aber verständlicher) ist die Verwendung des Moduloperators %:

private static boolean isEven(int number)
{
    if (number < 0)
       throw new ArgumentOutOfRangeException();

    return (number % 2) == 0;
}
Mitch Wheat
quelle
2
&ist auch logisch UND. &&Kurzschlüsse während &nicht.
Steve Kuo
5
number % 2ist nicht dasselbe wie number & 1wenn numberes negativ ist.
Dan04
4
Wenn Ihnen eine negative Länge übergeben wird, haben Sie größere Probleme! ;)
Mitch Wheat
4
@ RyanAmos "Jedes Bit iterieren?" Bitweises UND ist eine einzelne Operation in jeder CPU, die ich je gesehen habe - es gehört zu den einfachsten Dingen, die parallel ausgeführt werden können.
flauschig
2
@MitchWheat Es gibt keinen Grund, auf den number < 0Fall zu werfen - während eine ungerade negative Zahl Mod 2 -1 ist, ist eine gerade Mod 2 immer noch 0.
flauschig
8

Dieser Ausdruck bedeutet "die ganze Zahl repräsentiert eine gerade Zahl".

Hier ist der Grund warum: Die binäre Darstellung der Dezimalzahl 1ist 00000000001. Alle ungeraden Zahlen enden in einer 1binären Zahl (dies ist leicht zu überprüfen: Angenommen, die binäre Darstellung der Zahl endet nicht in 1; dann besteht sie aus Zweierpotenzen ungleich Null, was immer eine gerade Zahl ist). Wenn Sie eine Binärdatei ANDmit einer ungeraden Zahl erstellen, lautet das Ergebnis 1: Wenn Sie eine Binärdatei ANDmit einer geraden Zahl erstellen, ist das Ergebnis 0.

Dies war früher die bevorzugte Methode, um ungerade / gerade zurück zu entscheiden, als die Optimierer schlecht bis nicht vorhanden waren und die %Bediener die zwanzigfache Anzahl von Zyklen benötigten, die ein &Bediener benötigte. Wenn Sie dies tun number % 2 == 0, generiert der Compiler heutzutage wahrscheinlich Code, der so schnell wie möglich ausgeführt (number & 1) == 0wird.

Sergey Kalinichenko
quelle
5

Single &bedeutet bitweiser andOperator nicht Vergleich

Dieser Code prüft also, ob die erste bit(niedrigstwertige / ganz rechts) gesetzt ist oder nicht, was angibt, ob die Zahl ist oddoder nicht; weil alle ungeraden Zahlen mit 1dem niedrigstwertigen Bit enden, zxxxxxxx1

iTech
quelle
Beachten Sie, dass eine einzelne &als logische verwendet andwerden kann, wenn Sie Nebenwirkungen von Ausdrücken wief(x) & g(x)
Navin
4

&ist eine bitweise ANDOperation.

Für Nummer = 8:

  1000
  0001
& ----
  0000

Das Ergebnis ist das (8 & 1) == 0. Dies ist bei allen geraden Zahlen der Fall, da es sich um Vielfache von 2 handelt und die erste Binärziffer von rechts immer 0 ist. 1 hat einen Binärwert von 1 mit führenden Nullen. Wenn wir also ANDeine gerade Zahl verwenden, bleiben wir übrig mit 0.

Aram Kocharyan
quelle
3

Der &Operator in Java ist der bitweise Operator. Grundsätzlich (number & 1)führt eine bitweise-und zwischen numberund 1. Das Ergebnis ist entweder 0 oder 1, je nachdem, ob es gerade oder ungerade ist. Dann wird das Ergebnis mit 0 verglichen, um festzustellen, ob es gerade ist.

Hier ist eine Seite, die bitweise Operationen beschreibt .

rgettman
quelle
3

Es führt eine Binärdatei gegen 1 aus, die 0 zurückgibt, wenn das niedrigstwertige Bit nicht gesetzt ist

für dein Beispiel

00001010 (10)

00000001 (1)

===========

00000000 (0)

Peter Karlsson
quelle