Как отрицать только наименее значимые биты?

#bit-manipulation #bitwise-operators

Вопрос:

Начиная с позиции 1 бита высшего порядка, как я могу отрицать этот бит и все биты более низкого порядка?

Пример (C#)

 int inputNumber = 0b_10001;
inputNumber = ~inputNumber; // bitwise complement

int expectedNumber = 0b_000000000000000000000000000_01110;
uint actualNumber  = 0b_111111111111111111111111111_01110; // almost, but not quite
 

Подробные сведения

0b это просто маркер, чтобы начать писать число в двоичном формате. Это _ просто разделитель, чтобы визуально было легче следовать (но все еще действительный код C#). Пример: 0b_1010_1111 на самом деле 10101111 в двоичном формате.

Я чувствую, что близок к решению — мне нужно сделать маску, чтобы избавиться от нежелательных кусочков, но я не уверен, как это сделать.

Как я могу перейти от 10001 к 01110 , в основном отрицая каждый бит, но не имея ведущих 1 s?

Комментарии:

1. @njuffa, эта маска будет работать только для этого конкретного номера, а не для всех из них. Я должен посчитать количество установленных битов и иметь маску только для них, но все еще не могу понять, как это сделать.

2. Этот распространенный метод построения непрерывной маски справа создаст непрерывную группу из 1 бита справа от наиболее значимого 1 бита, вплоть до бита 0. Пример: 0b_10001 превратится в 0b_11111 . Я предполагаю четко определенный оператор сдвига вправо, что в C и C означает, что вы захотите использовать unsigned целочисленный тип для этих данных. Я не знаю, как C# определяет правильные сдвиги, в частности, с потенциально отрицательными целочисленными типами со знаком. Установив маску, вы можете затем использовать (0 - x) amp; m ее для выполнения нужного отрицания битового поля.

3. @njuffa, я попробовал маску из твоего первого комментария, но вместо этого я получаю 11101 11111 . Второй бит не установлен (я использовал unsigned и C ). Пример онлайн: cpp.sh/7ipif

4. Извини, я виноват. Правильный код: m = x; m = m | (m >> 16); m = m | (m >> 8); m = m | (m >> 4); m = m | (m >> 2); ; m = m | (m >> 1);

5. @njuffa, вау, это работает! Спасибо! Хотели бы вы опубликовать ответ, чтобы я мог проголосовать и согласиться отдать вам должное за вашу помощь?