Co oznacza ta wartość logiczna „(liczba & 1) == 0”?

79

Na CodeReview opublikowałem działający fragment kodu i poprosiłem o wskazówki, jak go ulepszyć. Jednym z nich było użycie metody boolowskiej, aby sprawdzić, czy ArrayList ma parzystą liczbę indeksów (co było wymagane). To był kod, który został zasugerowany:

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

Ponieważ już nagabywałem tego konkretnego użytkownika o dużą pomoc, zdecydowałem, że nadszedł czas, aby nękać społeczność SO! Naprawdę nie rozumiem, jak to działa. Metoda jest wywoływana i przyjmuje rozmiar ArrayList jako parametr (tj. ArrayList ma dziesięć elementów, liczba = 10).

Wiem, że pojedynczy &biegnie porównanie liczby i 1, ale potem się zgubiłem.

Sposób, w jaki to czytam, mówi, że zwróć prawdę jeśli number == 0i 1 == 0. Wiem, że to pierwsze nie jest prawdą, a drugie oczywiście nie ma sensu. Czy ktoś mógłby mi pomóc?

Edycja: Powinienem chyba dodać, że kod działa, na wypadek gdyby ktoś się zastanawiał.

Andrew Martin
źródło
2
Czy ktoś wie, kto połączył to z innym postem (który nie ma z tym nic wspólnego)? Czy mogę to jakoś usunąć?
Andrew Martin,
1
Cholera, to jest naprawdę sprytne!
cauon
2
Zostało to przedstawione na Twitterze.
Jonathon Reinhart
1
@GrijeshChauhan Czy mógłbyś wyjaśnić, w jaki sposób jest to szybsze niż number % 2 == 0?
Vrushank,

Odpowiedzi:

114

Pamiętaj, że „&” to operacja bitowa. Prawdopodobnie jesteś tego świadomy, ale nie jest to dla mnie całkowicie jasne, biorąc pod uwagę sposób, w jaki zadałeś pytanie.

To powiedziawszy, teoretyczna idea jest taka, że ​​masz jakieś int, które można wyrazić w bitach przez pewną serię jedynek i zer. Na przykład:

...10110110

W systemie binarnym, ponieważ ma podstawę 2, ilekroć wersja bitowa liczby kończy się na 0, jest parzysta, a gdy kończy się na 1, jest nieparzysta.

Dlatego zrobienie bitowego & z 1 dla powyższego to:

...10110110 & ...00000001

Oczywiście jest to 0, więc można powiedzieć, że oryginalne wejście było parzyste.

Alternatywnie rozważ liczbę nieparzystą. Na przykład dodaj 1 do tego, co mieliśmy powyżej. Następnie

...10110111 & ...00000001

Jest równa 1 i dlatego nie jest równa zeru. Voila.

Kirby
źródło
13
Dzięki - twoje wyjaśnienie jest bardzo jasne. Dodatkowo każda odpowiedź, która kończy się Voila, zasługuje na uznanie.
Andrew Martin,
1
Prawdopodobnie powinien również być świadomy liczb ujemnych w tej odpowiedzi.
Alvin Wong
3
Poza tym prawdopodobnie poprawiłbym tę odpowiedź, aby uwzględnić fakt, że n%k == n&(k-1)dla wszystkich, kktóre mają dodatnią potęgę 2. Może to nie być to, o co pytał pytający, ale warto wiedzieć.
puszysty
1
@fluffy nie mówi, że to nie zadziała, ale nie wszyscy znają uzupełnienie do dwóch.
Alvin Wong
1
@fluffy nie powinno być logani 2^gdzieś w tym wyrażeniu?
Navin
67

Możesz określić, czy liczba jest parzysta lub nieparzysta na podstawie ostatniego bitu w reprezentacji binarnej:

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

& między dwiema liczbami całkowitymi jest operatorem bitowym AND:

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

Więc jeśli (number & 1) == 0tak true, to znaczy, że numberjest równy.


Załóżmy zatem number == 6, że :

6 -> 00000000000000000000000000000110 (even)

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

1 -> 00000000000000000000000000000001

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

0 -> 00000000000000000000000000000000

a kiedy number == 7:

7 -> 00000000000000000000000000000111 (odd)

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

1 -> 00000000000000000000000000000001

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

1 -> 00000000000000000000000000000001
Eng. Fouad
źródło
18

&jest bitowym operatorem AND. &&jest operatorem logicznym AND

W systemie binarnym, jeśli bit cyfr jest ustawiony (tj. Jeden), liczba jest nieparzysta.

W systemie binarnym, jeśli bit cyfr jest równy zero, liczba jest parzysta.

(number & 1) jest bitowym testem AND bitu cyfr.

Innym sposobem na to (prawdopodobnie mniej wydajnym, ale bardziej zrozumiałym) jest użycie operatora modułu %:

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

    return (number % 2) == 0;
}
Mitch Wheat
źródło
2
&jest również logicznym AND. &&zwarcia, podczas gdy &nie.
Steve Kuo
5
number % 2to nie to samo, co number & 1jeśli numberjest ujemne.
dan04
4
jeśli otrzymujesz długość ujemną, masz większe problemy! ;)
Mitch Wheat,
4
@RyanAmos "Iterate each bit?" Bitowe AND to pojedyncza operacja w każdym procesorze, jaki kiedykolwiek widziałem - jest to jedna z najłatwiejszych czynności do wykonania równolegle.
puszysty
2
@MitchWheat Nie ma powodu, aby rzucać się w number < 0sprawę - podczas gdy nieparzysta liczba ujemna mod 2 to -1, parzysta mod 2 to nadal 0.
fluffy
8

To wyrażenie oznacza „liczba całkowita reprezentuje liczbę parzystą”.

Oto powód, dla którego: binarna reprezentacja liczby dziesiętnej 1to 00000000001. Wszystkie liczby nieparzyste kończą się na a 1w systemie dwójkowym (łatwo to zweryfikować: załóżmy, że binarna reprezentacja liczby nie kończy się na 1; wtedy składa się z niezerowych potęg dwóch, co zawsze jest liczbą parzystą). Kiedy robisz binarny ANDz liczbą nieparzystą, wynikiem jest 1; kiedy robisz binarny ANDz liczbą parzystą, wynikiem jest 0.

Była to preferowana metoda decydowania o parzystości / nieparzystości w czasach, gdy optymalizatory były słabe lub nieistniejące, a %operatorzy wymagali dwudziestokrotnej liczby cykli wykonywanych przez &operatora. W dzisiejszych czasach, jeśli to zrobisz number % 2 == 0, kompilator prawdopodobnie wygeneruje kod, który zostanie wykonany równie szybko, jak to (number & 1) == 0robi.

Sergey Kalinichenko
źródło
5

Pojedynczy &oznacza bitowy andoperator, a nie porównanie

Więc ten kod sprawdza, czy pierwszy bit(najmniej znaczący / najbardziej prawy) jest ustawiony, czy nie, co wskazuje, czy liczba jest, oddczy nie; ponieważ wszystkie liczby nieparzyste kończą się 1na najmniej znaczącym bicie, npxxxxxxx1

iTech
źródło
Zauważ, że singiel &może być użyty jako logiczny, andjeśli chcesz uniknąć skutków ubocznych z wyrażeń takich jakf(x) & g(x)
Navin
4

&jest ANDoperacją bitową .

Dla liczby = 8:

  1000
  0001
& ----
  0000

Wynik jest taki (8 & 1) == 0. Tak jest w przypadku wszystkich liczb parzystych, ponieważ są one wielokrotnościami 2, a pierwsza cyfra binarna od prawej to zawsze 0. 1 ma wartość binarną 1 z wiodącymi zerami, więc kiedy mamy ANDparzystą liczbę zostajemy z 0.

Aram Kocharyan
źródło
3

&Operator w Javie jest iloczynem bitowym i operator. Zasadniczo (number & 1)wykonuje bitowe i między numberi 1. Wynik to 0 lub 1, w zależności od tego, czy jest parzysty, czy nieparzysty. Następnie wynik jest porównywany z 0, aby określić, czy jest parzysty.

Oto strona opisująca operacje bitowe .

rgettman
źródło
3

Wykonuje operację binarną przeciwko 1, która zwraca 0, jeśli najmniej znaczący bit nie jest ustawiony

na przykład

00001010 (10)

00000001 (1)

===========

00000000 (0)

Peter Karlsson
źródło