Я думаю, что ответом является слегка измененное приложение примера getbits из раздела 2.9.
Давайте разберем его следующим образом:
Let bitstring x be 1 0 1 1 0 0
Let bitstring y be 1 0 1 1 1 1
positions -------->5 4 3 2 1 0
Установка p = 4 and n =3
дает нам цепочку битов из x, которая равна 0 1 1
. Он начинается в 4 и заканчивается в 2 и охватывает 3 элемента.
Мы хотим заменить 0 1 1
на 1 1 1
(последние три элемента цепочки бит y).
Давайте на время забудем о сдвиге влево / вправо и представим проблему следующим образом:
Нам нужно извлечь последние три цифры из строки битов y, которая равна 1 1 1
Разместите 1 1 1
непосредственно под позициями 4 3 and 2
цепочки битов x.
Заменить 0 1 1
на 1 1 1
, оставляя остальные биты нетронутыми ...
Теперь давайте углубимся в детали ...
Мое первое утверждение было:
We need to grab the last three digits from bitstring y which is 1 1 1
Способ изолировать биты от цепочки битов состоит в том, чтобы сначала начать с цепочки битов, которая имеет все 0.
Мы заканчиваем с 0 0 0 0 0 0
.
0 обладают этим невероятным свойством, где побитовое «&» с другим числом дает нам все 0, а побитовое «|» с другим числом возвращает нам это другое число.
0 само по себе здесь бесполезно ... но оно говорит нам, что если мы '|' последние три цифры y с '0', в итоге мы получим 1 1 1. Остальные биты в y на самом деле нас здесь не интересуют, поэтому нам нужно найти способ обнулить эти числа, сохраняя при этом последние три цифры без изменений. По сути нам нужен номер 0 0 0 1 1 1
.
Итак, давайте посмотрим на серию необходимых преобразований:
Start with -> 0 0 0 0 0 0
apply ~0 -> 1 1 1 1 1 1
lshift by 3 -> 1 1 1 0 0 0
apply ~ -> 0 0 0 1 1 1
& with y -> 0 0 0 1 1 1 & 1 0 1 1 1 1 -> 0 0 0 1 1 1
И таким образом у нас есть последние три цифры, которые будут использоваться для целей настройки ...
Мое второе утверждение было:
Поместите 1 1 1 непосредственно в позиции 4 3 и 2 цепочки битов x.
Подсказку для этого можно найти в примере getbits в разделе 2.9. То, что мы знаем о позициях 4,3 и 2, можно узнать из значений p = 4 and n =3
. p - это позиция, а n - длина набора битов. Оказывается, p+1-n
дает нам смещение набора битов от самого правого бита. В этом конкретном примере p+1-n = 4 +1-3 = 2
.
Итак ... если мы сделаем сдвиг влево на 2 строки 0 0 0 1 1 1
, мы получим 0 1 1 1 0 0
. Если вы поместите эту строку в x, вы заметите, что 1 1 1
совпадает с позициями 4 3 and 2
в x.
Мне кажется, я наконец-то кое-что получил ... последнее заявление, которое я сделал ...
Заменить 0 1 1 на 1 1 1, оставив остальные биты нетронутыми ...
Теперь рассмотрим наши строки:
x -> 1 0 1 1 0 0
isolated y -> 0 1 1 1 0 0
Выполнение побитового или с этими двумя значениями дает нам то, что нам нужно для этого случая:
1 1 1 1 0 0
Но это не получится, если вместо 1 1 1
у нас будет 1 0 1
... поэтому, если нам нужно еще немного покопаться, чтобы добраться до нашей "серебряной пули" ...
Давайте посмотрим на две вышеупомянутые строки еще раз ...
x -> bit by bit...1(stays) 0(changes) 1(changes) 1(changes) 0(stays) 0(stays)
Так что в идеале ... нам нужна цепочка битов 1 x x x 0 0
, где x поменяется местами с 1.
Вот прыжок интуиции, который поможет нам ..
Bitwise complement of isolated y -> 1 0 0 0 1 1
& this with x gives us -> 1 0 0 0 0 0
| this with isolated y -> 1 1 1 1 0 0 (TADA!)
Надеюсь, этот длинный пост поможет людям рационализировать и решить такие проблемы с маскировкой ...
Спасибо