Увеличение "маскированных" наборов битов
в настоящее время я пишу перечислитель дерева, где я столкнулся со следующей проблемой:
Я смотрю на маскированные битовые наборы, т. е. битовые наборы, где установленные биты являются подмножеством маски, т. е. 0000101
с маской 1010101
. То, что я хочу сделать, - это увеличить битовый набор, но только по отношению к маскированным битам. В этом примере результатом будет 0010000
. Чтобы сделать его немного яснее, извлеките только замаскированные биты, т. е. 0011
, увеличьте их до 0100
и распределите их на биты маски снова, давая 0010000
.
кто-нибудь видит эффективный способ сделать это, за исключением реализации операции вручную с использованием комбинации битов и префиксных масок?
3 ответа:
просто заполните не маски битов с теми, так что они распространяются нести:
// increments x on bits belonging to mask x = ((x | ~mask) + 1) & mask;
хотя это и не интуитивно понятно по сравнению с принятым ответом, это работает всего за 3 шага:
x = -(x ^ mask) & mask;
Это можно проверить, как предложил zch:
-(x ^ mask) = ~(x ^ mask) + 1 // assuming 2's complement = (x ^ ~mask) + 1 = (x | ~mask) + 1 // since x and ~mask have disjoint set bits
тогда это становится эквивалентным принятому ответу.
если порядок итерации не так важен, и операция декремента удовлетворит ваши потребности, можно использовать только две операции:
С
x = mask
и получить Предыдущее значение
x = (x - 1) & mask
x - 1
часть изменений последнего ненулевого бита на ноль, а все менее значимые биты с 1 по. Затем& mask
часть оставляет только биты маски среди них.