почему это работает? (поиск нечетного числа в C++)

for (unsigned int i = 1; i <= 100; i++) {
    if (i & 0x00000001) {
        std::cout << i<<",";
    }
}

почему (и как): if( i & 0x00000001 ) выяснить нечетное число?

9 ответов


0x00000001 is 1 в двоичном формате, хотя он написан в шестнадцатеричной (base-16) нотации. Это 0x часть.

& является битовым оператором "и", который используется для выполнения двоичных разрядных (битных) манипуляций.

i & 1 преобразует все двоичные цифры i в ноль, за исключением последнего.

это просто преобразовать результирующее 1-разрядное число в логическое, для оценки по if заявление.

следующий диаграмма показывает последние 16 двоичных цифр i и то, что с ними происходит.

i:   i in binary:        i & 1 in binary:    convert to boolean
---- ------------------- ------------------- ---------------------
1    0000000000000001    0000000000000001    true
2    0000000000000010    0000000000000000    false
3    0000000000000011    0000000000000001    true
4    0000000000000100    0000000000000000    false
5    0000000000000101    0000000000000001    true
6    0000000000000110    0000000000000000    false
7    0000000000000111    0000000000000001    true
8    0000000000001000    0000000000000000    false
...  ...                 ...                 ...
99   0000000001100011    0000000000000001    true
100  0000000001100100    0000000000000000    false

Он использует побитовый оператор "и", чтобы замаскировать все, кроме последнего бита. Если последний бит равен 1, то число нечетное. Этого объяснения достаточно?


когда мы смотрим на числа в базе 10, легко сказать, делится ли число на 10: оно имеет 0 в последней позиции. Код выше также смотрит на цифру в последней позиции, но в базе 2. Если он ненулевой, то число не делится на 2.


он маскирует последний бит. Если вы посмотрите на каждое место в двоичном представлении числа (..., 256, 128, 64, 32, 16, 8, 4, 2, и 1), Вы заметите, что единственное место-это странно. Все остальные места имеют четное значение, установлены ли биты или очищены (ноль четный). И добавление четных чисел всегда дает четное число. Только это последнее место определяет четность числа. The i & &0x00000001 часть просто изолирует место последнего.


нечетные числа - это все числа вида (2*n+1), где n-любое целое число (-2, -1,0,1....). Поэтому, чтобы найти нечетное число, вы должны увидеть, имеет ли целое число, с которым вы работаете, это "+1". Когда хранится как беззнаковое целое число можно выразить, как сумму сил 2: 2^0 + 2^1 +2^2 + 2^4, и т. д. Двоичная версия беззнакового целого числа выглядит как своего рода карта истинности: для каждого места в двоичном числе есть "1", добавьте эту силу двух к числу. Итак, если вы начнете в правом самом значном двоичном представлении целого числа без знака и перемещении влево каждая цифра представляет собой степень двух. Если цифра равна 1, то вы добавляете эту силу двух к текущей сумме и когда вы достигнете конца двоичного числа.

таким образом: 10001110b можно преобразовать в целое число, суммируя степени двух:

Правый: 2^1 + 2^2 + 2^3 + 2^7 :Левый = 141

фокус в том, что самая правая цифра представляет 2^0. Это всегда 1. Все остальные цифры представляют собой четные числа. Итак, с точки зрения нечетных чисел вы должны найти "+1". Это соответствует самой правой цифре. Все остальные цифры представляют собой числа вида '2*n'. Поэтому, чтобы определить, если число этого формата (целое число без знака) нечетно, вам нужно только увидеть, является ли самый правый бит "1".

операция, выполняемая над целым числом без знака, является логической операцией И. Что-нибудь и с 0 равно 0, а 1 и с 1 равно 1. Таким образом, операция приведет к тому, что все двоичные цифры в целочисленном представлении без знака будут равны 0, за исключением двоичной цифры, представляющей 2^0 (что равно 1). Таким образом, целочисленное двоичное представление без знака будет сводиться к 0x00000001, если оно нечетное, и 0x00000000, если оно четное.

Примечание: когда я пишу 0x00000000, " 0x " означает, что это шестнадцатеричный формат. Каждый " 0 " представляет четыре бита. Так 0х00 шестнадцатеричное 00000000b Записано в двоичном формате, полученное возможное целое число без знака двоичные представления после and'ING целое число без знака:

00000000000000000000000000000000b == 0 и 00000000000000000000000000000001b == 1


вы делаете побитовое сравнение. Если bit0 и bit0 равны 1, то ответ bit0 = 1.

видя, что &0x00000001 равно 1, любые числа с этим битом нечетны.

0x00000001 = 1
0x00000010 = 2
0x00000011 = 3
etc.

Итак, если вы сделаете побитовое и

00000001 AND 
00000001 = 
00000001 (same as true)

00000010 AND 
00000001 = 
00000000 (same as false)

00000011 AND 
00000001 = 
00000001 (same as true)

etc

прежде чем я скажу следующее, Я сначала скажу, что я в значительной степени всегда использую бит-тест, чтобы определить, является ли int нечетным или четным.

но, строго говоря, вы должны использовать (i % 2) или ((i % 2) != 0) определить i - это странно. Это будет работать независимо от представления отрицательных чисел, в то время как на машине дополнения (-3 & 0x01) будет возвращен ноль (ложный результат), хотя это явно нечетно.

Я понимаю, что machiens, которые используют что-то другое чем два дополнения для представления отрицательного числа очень и очень редки в наши дни, но это также правда, что компиляторы в наши дни будут универсально компилировать (i % 2) немного проверить в любом случае. И помните, я обычно не следую своим собственным советам здесь, так что это может быть показателем истинной ценности этого предложения.


побитовый оператор AND следует этой таблице истинности для каждого бита:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Поскольку компьютеры работают с числами с основанием 2 и каждый бит представляет два значения (1,2,4,8,16 ..),
наименьший бит представляет единственное нечетное число, независимо от того, большое или малое значение, и независимо от того, подписано оно или нет. Поскольку результирующий бит устанавливается только в том случае, если оба операнда имеют этот бит, результат истинен тогда и только тогда, когда число нечетно.

Образец: 0b11101011 =
(1 * 2^0) + (1 * 2^1) + (0 * 2^2) + (1 * 2^3) +
(0 * 2^4) + (1 * 2^5) + (1 * 2^6) + (1 * 2^7) =
1 + 2 + 0 + 8 + 0 + 32 + 64 + 128 = 235
Без наименее значимого набора битов значение будет 234 и, следовательно, четным числом.


например, как мы делаем двоичный эквивалент

8 4 2 1

0 0 0 0 = 0

0 0 0 1 = 1

0 0 1 0 = 2

0 0 1 1 = 3

Так что вы можете видеть какой-либо нет. LSB всегда установлен, то же самое вы проверяете:)

надеюсь, мой ответ ясен