Що означає це логічне значення "(число & 1) == 0"?


79

На CodeReview я опублікував робочий фрагмент коду і попросив поради щодо його вдосконалення. Одним із отриманих я був використання булевого методу, щоб перевірити, чи має ArrayList парну кількість індексів (що потрібно). Це був запропонований код:

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

Оскільки я вже дошкуляв конкретному користувачеві за велику допомогу, я вирішив, що настав час приставати до спільноти SO! Я насправді не розумію, як це працює. Метод викликається і приймає за параметр розмір ArrayList (тобто ArrayList має десять елементів, число = 10).

Я знаю, що сингл &запускає порівняння як числа, так і 1, але я загубився після цього.

Як я це читаю, це означає повернення істини, якщо number == 0і 1 == 0. Я знаю, що перше не відповідає дійсності, а друге, очевидно, не має сенсу. Хтось може мені допомогти?

Редагувати: Ймовірно, слід додати, що код справді працює, якщо хтось цікавиться.


2
Хто-небудь знає, хто пов’язав це з тим іншим постом (який не має нічого спільного з цим матеріалом)? Чи можу я це якось видалити?
Andrew Martin

1
Блін, це насправді по-справжньому розумно!
cauon

2
Це було розміщено у Twitter.
Джонатан Рейнхарт,


1
@GrijeshChauhan Не могли б ви уточнити, як це швидше, ніж number % 2 == 0??
Vrushank

Відповіді:


114

Майте на увазі, що "&" - побітова операція. Ви, мабуть, це знаєте, але мені не зовсім зрозуміло, виходячи з того, як ви поставили запитання.

Тим не менше, теоретична ідея полягає в тому, що у вас є деякий int, який може бути виражений у бітах деякими серіями 1s і 0s. Наприклад:

...10110110

У двійковій системі, оскільки вона є базовою 2, коли побітова версія числа закінчується на 0, вона є парною, а коли закінчується на 1 - непарною.

Отже, робити побітове & з 1 для вищезазначеного:

...10110110 & ...00000001

Звичайно, це 0, тож можна сказати, що вихідне введення було рівним.

Як варіант, розглянемо непарне число. Наприклад, додайте 1 до того, що ми мали вище. Тоді

...10110111 & ...00000001

Дорівнює 1, а значить, не дорівнює нулю. Вуаля.


13
Дякую - ваше пояснення робить це дуже чітким. Плюс будь-яка відповідь, яка закінчується вуаля, заслуговує на підтримку.
Andrew Martin

1
Мабуть, також слід знати про негативні числа в цій відповіді.
Елвін Вонг,

3
Крім того, я міг би, можливо, змінити цю відповідь, включивши той факт, що n%k == n&(k-1)для всіх, kхто є позитивною степенем 2. Це може бути не те, про що запитував запитувач, але це корисно знати.
пухнастий

1
@fluffy не каже, що це не спрацює, але не всі знають доповнення двох.
Елвін Вонг

1
@fluffy не повинно бути logабо 2^десь у цьому виразі?
Navin

67

Ви можете визначити число або парне, або непарне за останнім бітом у його двійковому поданні:

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

& між двома цілими числами є побітовий оператор І:

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

Отже, якщо (number & 1) == 0є true, це означає number, що парне.


Припустимо, що number == 6тоді:

6 -> 00000000000000000000000000000110 (even)

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

1 -> 00000000000000000000000000000001

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

0 -> 00000000000000000000000000000000

і коли number == 7:

7 -> 00000000000000000000000000000111 (odd)

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

1 -> 00000000000000000000000000000001

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

1 -> 00000000000000000000000000000001

18

&є побітовим оператором І. &&є логічним оператором І

У двійковому вигляді, якщо встановлений біт цифр (тобто один), число непарне.

У двійковому вигляді, якщо розряд цифр дорівнює нулю, число парне.

(number & 1) є побітовим І тестом розряду цифр.

Інший спосіб зробити це (і, можливо, менш ефективний, але більш зрозумілий) - використання оператора модуля %:

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

    return (number % 2) == 0;
}

2
&також є логічним І. &&коротких замикань поки &немає.
Steve Kuo

5
number % 2не те саме, що number & 1якби numberє від’ємним.
dan04

4
якщо вам передають негативну довжину, то у вас є більші проблеми! ;)
Mitch Wheat

4
@RyanAmos "Ітерацію кожного біта?" Побітове І - це одна операція в кожному процесорі, яку я коли-небудь бачив - це одна з найпростіших речей, які можна робити паралельно.
пухнастий

2
@MitchWheat Немає причин кидати number < 0справу - в той час як непарне від'ємне число mod 2 дорівнює -1, парне mod 2 все одно 0.
пухнастий

8

Цей вираз означає "ціле число представляє парне число".

Ось причина: двійкове представлення десяткової 1є 00000000001. Усі непарні числа закінчуються 1двійковою системою a (це легко перевірити: припустимо, двійкове подання числа не закінчується 1; тоді воно складається з ненульових степенів із двох, що завжди є парним числом). Коли ви робите двійковий файл ANDз непарним числом, результат є 1; коли ви робите двійковий файл ANDз парним числом, результат є 0.

Раніше це був найкращий метод прийняття рішення щодо непарних / парних результатів у той час, коли оптимізатори були слабкими або неіснуючими, а %операторам потрібно було в двадцять разів більше циклів, взятих &оператором. У наші дні, якщо ви це зробите number % 2 == 0, компілятор, швидше за все, згенерує код, який виконується так само швидко, як (number & 1) == 0це робиться.


5

Одиничний &означає бітовий andоператор, а не порівняння

Отже, цей код перевіряє, чи встановлений перший bit(найменш значущий / найбільш правильний), що вказує, чи є число oddчи ні; тому що всі непарні числа закінчуватимуться 1найменш значущим бітом, наприкладxxxxxxx1


Зверніть увагу, що сингл &можна використовувати як логічний, andякщо ви хочете зберегти побічні ефекти від таких виразів, якf(x) & g(x)
Navin

4

&є побітовою ANDоперацією.

Для числа = 8:

  1000
  0001
& ----
  0000

Результат такий (8 & 1) == 0. Це стосується всіх парних чисел, оскільки вони кратні 2, а перша двійкова цифра праворуч завжди дорівнює 0. 1 має двійкове значення 1 із провідними 0, тому, коли ми отримуємо ANDпарне число, ми залишаємось з 0.


3

&Оператор в Java є побітовим і оператором. В основному, (number & 1)виконує побітове значення - а між numberі 1. Результат - 0 або 1, залежно від того, парний він чи непарний. Потім результат порівнюється з 0, щоб визначити, чи він рівний.

Ось сторінка з описом побітових операцій .


3

Він виконує двійковий файл і проти 1, який повертає 0, якщо найменший значущий біт не встановлений

для вашого прикладу

00001010 (10)

00000001 (1)

===========

00000000 (0)


3

Це концепція логічного дизайну побітовим оператором & (І).

повернення (2 & 1); означає - перетворити значення в побітові числа та зрозуміти функцію (І) і повернути значення.

Віддайте перевагу цьому посиланню http://www.roseindia.net/java/master-java/java-bitwise-and.shtml

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.