Увеличение "маскированных" наборов битов
в настоящее время я пишу перечислитель дерева, где я столкнулся со следующей проблемой:
Я смотрю на маскированные битовые наборы, т. е. битовые наборы, где установленные биты являются подмножеством маски, т. е. 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часть оставляет только биты маски среди них.