Кто-нибудь может помочь чем n&-n
средства??
И каково это значение.
Я считаю, что это уловка, чтобы выяснить, если n является степенью 2. (n == (n & -n)) IFF n является степенью 2 (1,2,4,8).
Это старый трюк, который дает число с одним битом, нижний бит, который был установлен в n
, По крайней мере, в арифметике с двумя дополнениями, которая сегодня почти универсальна.
Причина, по которой это работает: отрицание числа получается путем инвертирования числа с последующим добавлением 1 (это определение дополнения до двух). Когда вы добавляете 1, каждый бит, начинающийся с нижнего установленного значения, будет перетекать в следующий старший бит; это останавливается, как только вы достигнете нулевого бита. Все эти переполненные биты будут равны нулю, а биты выше последнего затронутого будут обратными друг другу, поэтому единственный оставшийся бит — это тот, который остановил каскад — тот, который начинался как 1 и был инвертирован в 0.
Постскриптум Если вы беспокоитесь о том, чтобы столкнуться со своей арифметикой, вот версия, которая работает с обоими:
n & (~n + 1)
Практически во всех системах, которые действительно интересуют большинство людей, это даст вам наибольшую степень 2, на которую n делится поровну.
Это просто поразрядно — и из числа. Отрицательные числа представлены как дополнение двух.
Так, например, поразрядно и 7&(-7) это x00000111 & x11111001 = x00000001 = 1
N&(-N)
даст вам позицию первый немного '1'
в двоичном виде N
,
Например:
N = 144 (0b10010000) => N&(-N) = 0b10000
N = 7 (0b00000111) => N&(-N) = 0b1
Одним из применений этого трюка является преобразование целого числа в сумму степени 2.
Например:
To convert 22 = 16 + 4 + 2 = 2^4 + 2^2 + 2^1
22&(-22) = 2, 22 - 2 = 20
20&(-20) = 4, 20 - 4 = 16
16&(-16) = 16, 16 - 16 = 0
Я хотел бы добавить очевидный пример к Марк РэндсомПрекрасная экспозиция.
010010000 | +144 ~
----------|-------
101101111 | -145 +
1 |
----------|-------
101110000 | -144
101110000 | -144 &
010010000 | +144
----------|-------
000010000 | 16`
Так как x & -x = {0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 32}
за x
от 0 до 32. Используется для перехода в последовательности for для некоторых приложений. В приложениях можно хранить накопленные записи.
for(;x < N;x += x&-x) {
// do something here
++tr[x];
}
Цикл проходит очень быстро, потому что он ищет следующую степень двойки для прыжка.
Как уже упоминал @aestrivex, это способ написания 1. Даже я сталкивался с этим
for (int y = x; y > 0; y -= y & -y)
и это просто означает, что у = у-1, потому что
7&(-7) это x00000111 & x11111001 = x00000001 = 1