Как инвертировать только определённые биты в числе
Мне нужно инвертировать все биты в числе, допустим, 2 ( 10 в двоичной системе) после инвертирования будет равно 01 . Но столкнулся с проблемой, что операция побитового отрицания инвертирует также и знаковый бит и вообще все биты, которыми число представлено в памяти. И получается, что:
int a = ~2; // -3
Как мне всё-таки получить 1 , а не -3 ?
Отслеживать
28.5k 12 12 золотых знаков 58 58 серебряных знаков 118 118 бронзовых знаков
задан 8 фев 2019 в 7:31
IWProgrammer IWProgrammer
831 1 1 золотой знак 15 15 серебряных знаков 28 28 бронзовых знаков
как же так, 2 — это . 00010 после инвертирования будет. 11101. Поставьте явную задачу
8 фев 2019 в 7:45
5 ответов 5
Сортировка: Сброс на вариант по умолчанию
Вообще-то битовые операции не стоит применять к знаковым целым числам, поэтому я пишу сразу для unsigned .
Увы, из вашего задания мало что понятно. Вы хотите, похоже, инвертировать только биты, начиная со старшего единичного бита?
000010000101 -> 000001111010 000011111111 -> 000000000000
unsigned int inv(unsigned int x) < unsigned int mask = 0; for(unsigned int y = x;y;y>>=1) (mask
Здесь для 0 все же инвертируем его в 1.
Но вот не уверен, что вы хотите для 7 или там 3 инвертирование в 0 — все их единички.
А вообще — нужно очень точное ТЗ, иначе результатом будет ХЗ.
С тем же успехом, для @avp:
mov eax, d bsr ecx, eax inc ecx mov ebx, 1 shl ebx, cl dec ebx dec ebx or ebx, 1 xor d, ebx
Что значит инвертируем все биты числа
Здравствуйте.
Вот осваиваю побитовые операции, столкнулся с проблемой: как проверить установлен ли N’ный бит и как его установить, снять?
И может кто знает, где почитать что-нибудь по теории работы на битовом уровне? Я уже кучу сайтов пролазил, почти везде дальше пары абзацев по побитовым операторам не заходит.
Re: Побитовые операции
| От: | Алекс Пронскявичус |
| Дата: | 06.08.02 00:48 |
| Оценка: |
Сорри, на первый вопрос ответ нашел в архиве.
Re: Побитовые операции
| От: | Dr_Sh0ck | |
| Дата: | 06.08.02 04:49 | |
| Оценка: | 7 (2) | |
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Здравствуйте.
АП>Вот осваиваю побитовые операции, столкнулся с проблемой: как проверить установлен ли N’ный бит и как его установить, снять?
Я так понял, ответ на первый вопрос ты нашел.
Устанавливается бит операцией OR (логичексое сложение): первым операндом является переменная, где ты хочешь установить бит(ы), а вторым операндом — число, в котором нужные для установки в первом числе биты выставлены в 1:
char c; c |= 1; // устанавливает 0-ой бит в с с |= 2; // устанавливает 1-ый бит в с c |= 3; // устанавливает 0-ой и 1-ый биты в с
и т.д. по степеням двойки
«сбрасываеся» в 0 бит операцией AND (логическое умножение): первым операндом является переменная, где ты хочешь сбросить бит(ы), а вторым операндом — число, в котором нужные для сброса в первом числе биты выставлены в 0:
char c; c &= 1; //сбрасывает 0-ой бит в с с &= 2; // сбрасывает 1-ый бит в с c &= 3; // сбрасывает 0-ой и 1-ый биты в с
Чтобы инвертировать (изменить значение на противоположное — 0 на 1; 1 на 0) бит(ы) проименияется операция XOR (исключение ИЛИ): первым операндом является переменная, где ты хочешь инвертировать бит(ы), а вторым операндом — число, в котором нужные для инверсии в первом числе биты выставлены в 1:
char c; c ^= 1; //инвертирует 0-ой бит в с с ^= 2; //инвертирует 1-ый бит в с c ^= 3; //инвертирует 0-ой и 1-ый биты в с
АП>И может кто знает, где почитать что-нибудь по теории работы на битовом уровне? Я уже кучу сайтов пролазил, почти везде дальше пары абзацев по побитовым операторам не заходит.
Вообщем, любая книга по ассемблеру, большинтсво книг по С.
Do not fake yourself 😉
ICQ#: 198114726
Re[2]: Побитовые операции
| От: | ppp | |
| Дата: | 06.08.02 05:20 | |
| Оценка: | 20 (4) | |
Здравствуйте Dr_Sh0ck, Вы писали:
DS>»сбрасываеся» в 0 бит операцией AND (логическое умножение): первым операндом является переменная, где ты хочешь сбросить бит(ы), а вторым операндом — число, в котором нужные для сброса в первом числе биты выставлены в 0:
DS>
DS>char c; DS>c &= 1; //сбрасывает 0-ой бит в с DS>с &= 2; // сбрасывает 1-ый бит в с DS>c &= 3; // сбрасывает 0-ой и 1-ый биты в с DS>
С этим я не согласен. Операция
b &= flag
оставляет только те биты в байте b, которые совпадают и в байте и во флаге. Например,
10 & 8 = 8, тк в двоичной записи это выглядит так
1010 & 1000 = 1000
10 & 1 = 0, тк в двоичной записи это выглядит так
1010 & 0001 = 0000
Сбросить в 0 нужный бит можно следующей операцией
b &= ~flag (~ это инвертирование байт в бите)
сбрасываем 4й бит
10 & ~8 = 2, тк в двоичной записи это выглядит так
1010 & ~1000 = 1010 & 0111 = 0010
сбрасываем 2й и 3й биты (флаг = 6)
10 & ~6 = 8, тк в двоичной записи это выглядит так
1010 & ~0110 = 1010 & 1001 = 1000
От себя порекомендую следующие очень полезные битовые операции:
>> — сдвиг вправо
Кроме того, следует учесть, что для битовых операций лучше пользоваться беззнаковыми целыми, тк иначе ты долго будешь ломать голову, почему
int c = 10;
c >>= 2 даст в результате 2, но
int d = -10;
d >>= 2 даст в результате 0xfffffffd (существует правило, что знаковые целые при сдвиге вправо заполняются слева единицами)
если же пользоваться беззнаковыми целыми, то все прозрачно
unsigned u = -10; //0xfffffff6
u >>= 2 даст в результате 0x3ffffffd
Если ты такой умный, почему ты такой бедный?
Re[3]: Побитовые операции
| От: | Dr_Sh0ck |
| Дата: | 06.08.02 06:09 |
| Оценка: |
Здравствуйте ppp, Вы писали:
ppp>Здравствуйте Dr_Sh0ck, Вы писали:
DS>>»сбрасываеся» в 0 бит операцией AND (логическое умножение): первым операндом является переменная, где ты хочешь сбросить бит(ы), а вторым операндом — число, в котором нужные для сброса в первом числе биты выставлены в 0:
DS>>
DS>>char c; DS>>c &= 1; //сбрасывает 0-ой бит в с DS>>с &= 2; // сбрасывает 1-ый бит в с DS>>c &= 3; // сбрасывает 0-ой и 1-ый биты в с DS>>
ppp>С этим я не согласен. Операция
Ну, конечно, блин, опозорился. Это я так хотел ответить побыстрее
Операции вставки/копирования, конечно, удобны, но иногда неплохо все вручныю писАть — еньше шансов на вот такие глупые ошибки.
P.S. Кто сильно матерился на мой ответ, прошу прощения
Do not fake yourself 😉
ICQ#: 198114726
Re: Побитовые операции
| От: | Аноним |
| Дата: | 06.08.02 06:15 |
| Оценка: |
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Здравствуйте.
АП>Вот осваиваю побитовые операции, столкнулся с проблемой: как проверить установлен ли N’ный бит и как его установить, снять?
АП>И может кто знает, где почитать что-нибудь по теории работы на битовом уровне? Я уже кучу сайтов пролазил, почти везде дальше пары абзацев по побитовым операторам не заходит.
const unsigned char bitMask = 0b00100000;
unsigned char yourVar;
Re[2]: Побитовые операции
| От: | Аноним |
| Дата: | 06.08.02 06:31 |
| Оценка: |
Здравствуйте Аноним, Вы писали:
А>Здравствуйте Алекс Пронскявичус, Вы писали:
АП>>Здравствуйте.
АП>>Вот осваиваю побитовые операции, столкнулся с проблемой: как проверить установлен ли N’ный бит и как его установить, снять?
АП>>И может кто знает, где почитать что-нибудь по теории работы на битовом уровне? Я уже кучу сайтов пролазил, почти везде дальше пары абзацев по побитовым операторам не заходит.
А>const unsigned char bitMask = 0b00100000;
А это где такое бывает?
Re[2]: Побитовые операции
| От: | Алекс Пронскявичус |
| Дата: | 06.08.02 07:21 |
| Оценка: |
Здравствуйте Dr_Sh0ck, Вы писали:
DS>Вообщем, любая книга по ассемблеру, большинтсво книг по С.
Ага! В книгах по С тоже есть, а я уж думал придётся читать что-то по ассемблеру.
Re[3]: Побитовые операции
| От: | Алекс Пронскявичус |
| Дата: | 06.08.02 07:21 |
| Оценка: |
Здравствуйте ppp, Вы писали:
Битовое представление чисел и операции с ними
Допустим, есть задача, сформулированная следующим образом: >. Первым делом мы зададим вопрос, а где у числа первый бит? Если бы вопрос был сформулирован в терминах страших/младших битов, то все сомнения бы отпали.
Дело в том, что может быть и так, и так. В зависимости от архитектуры операционной системы порядок бит при записи их в памяти будет разным. Различают big-endian и little-endian.
При схеме little-endian сначала идут младшие биты. Например, число $100_$ записывалось в двоичной записи так: $0010011$.
При записи в формате big-endian сначала идут старшие биты. В абзаце выше все примеры даны в big-endian формате.
Если в условиях задачи нельзя однозначно определить требуемый формат записи, то надо следовать следующему алгоритму:
- Внимательно посмотреть на тесты и попробовтаь определить из них формат.
- Только в случае, если предыдущий шаг не сработал, обратиться к преподавателям за дополнительным примером.
Операции с битами
- a & b = 1 $\Leftrightarrow$ a = 1 и b = 1. AND
- a | b = 1 $\Leftrightarrow$ a = 1 или b = 1. OR
- a ^ b = 1 $\Leftrightarrow$ $a \neq b$. XOR
- ~a = 0 $\Leftrightarrow$ a = 1, ~a = 1 $\Leftrightarrow$ a = 0. Инверсия бита
- $13$ & $7$ = $1101_2$ & $0111_2$ = $0101_2$ = $5$
- $17$ | $10$ = $10001_2$ | $01010_2$ = $11011_2$ = $27$
- $17$ ^ $9$ = $10001_2$ ^ $01001_2$ = $11000_2$ = $24$
Выделить i-й бит числа
Сразу скажем, что $i$-й, начиная с младших бит, нумерация с нуля. Пусть исходное число равно $A$.
выделить 2-й бит в числе 21:
Выставить i-й бит числа в единицу
То есть надо сделать так, что на $i$-й позиции битовой записи числа стояла единица.
Инвертировать все биты числа
Получить число, состоящее из k единиц
Если такое число сдвинуть на несколько битов влево, то получим маску из $k$ единиц, которой можно выделять (с помощью побитового «И») произвольные k бит числа.
Автор конспекта: Полина Романченко
По всем вопросам пишите в telegram @Romanchenko
C/C++ Работа с битами
В Си существуют 6 операторов для манипулирования битами:
>> — сдвиг вправо
~ — поразрядная инверсия
| — поразрядное ИЛИ
& — поразрядное И
^ — поразрядное исключающее ИЛИ
Если нужно записать сразу несколько бит:
unsigned char x = 0; x = 1Номера битов отсчитываются справа налево, начиная с нуля. 0 — это младший бит (справа), 7 — это старший бит (слева).
Если нужно записывать определенные биты, не стирая другие:
Чтобы записать единицу в бит n:
x |= (1Чтобы записать ноль в бит n:
x &= ~(1Если нужно инвертировать состояние бита:
x ^= (1Если нужно прочитать отдельный бит:
unsigned char x = (1 if (x & (1 /* во второй бит вписана единица */ > if (x & (1 /* в третий бит вписана единица */ > if (x & (1 /* в седьмой бит вписана единица */ >Если нужно определить, что в X на N-й позиции:
bool b = (bool((1Если нужно обнулить один или несколько битов:
Для обнуления отдельных битов используется оператор &
int x = 58; // 00111010 int y = x & 0x0F; // 00001010Обнулить несколько битов можно и так:
x = x & (~((1<<3)|(1<<5)|(1<<6))); //обнуляем третий, пятый и шестой битыЕсли нужно установить заданные биты в единицу. Используют оператор |
int x = 155 x = x | 4; //устанавливаем в единицу второй бит переменной x155 0b10011011 | 4 0b00000100 159 0b10011111Сдвиг влево
Сдвигает число на n разрядов влево
unsigned char x = 3; //0b00000011 x = x //0b00011000 (24)Сдвиг вправо >>
Сдвигает число на n разрядов вправо
unsigned char x = 255; //0b11111111 x = x >> 3; //0b00011111 (31)