Битовые операции в языке Си. Восьмеричные и шестнадцатеричные числа
Данный урок курса можно считать факультативным, т. е. необязательным. Для освоения темы этого урока вам потребуется знание о двоичной системе счисления, навыки перевода чисел из одной системы счисления в другую, а также вы должны иметь представление о том, что такое битовые (они же поразрядные) операции. С последним можно познакомиться по вот этой лекции.
В языке программирования C существуют следующие поразрядные операции: & (И), | (ИЛИ), ^ (исключающее ИЛИ), > (сдвиг вправо), ~ (поразрядное дополнение до единицы). Рассмотрим на примерах, как они работают, но перед этим уделим внимание выводу чисел в отличных от десятичной системах счисления.
В C можно присваивать целочисленные значения в десятичной, восьмеричной и шестнадцатеричной системах счисления. Для того, чтобы присвоить переменной число в восьмеричной системе счисления, перед ним надо написать 0 (ноль), в шестнадцатеричной — 0x (ноль и икс), например:
int a, b; a = 077; // восьмеричное число b = 0x1F; // шестнадцатеричное число
Любые целые числа можно выводить на экран в десятичном, восьмеричном и шестнадцатеричном представлении. Пример кода для вывода определенных ранее двух переменных в различных системаъ счисления:
printf("%d %o %x %X\n", a, a, a, a); printf("%d %o %x %X\n", b, b, b, b);
В результате на экране вы увидите:
63 77 3f 3F 31 37 1f 1F
Восьмеричные и шестнадцатеричные числа используются из-за удобства при работе с двоичной системой счисления. Каждая цифра восьмеричного числа может быть заменена тремя цифрами двоичного. И каждая цифра шестнадцатеричного числа легко заменяет четыре разряда двоичного числа. Вот таблица соответствия цифр восьмеричной системы счисления числам двоичной системы:
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
Теперь допустим, что у нас есть восьмеричное число 037. По таблице легко понять, что в двоичном выражении оно будет выглядеть как 011 111.
Шестнадцатеричное число 7D в двоичной системе счисления будет выглядеть как 0111 1101.
Если бы мы при работе с поразрядными операциями использовали десятичные числа, то чтобы оценить результат нам бы каждый раз приходилось переводить десятичное число в двоичную систему счисления, что относительно трудоемко. Если же человек видит, например, восьмеричное число, то он может представить как оно выглядит в двоичном представлении, помня или держа перед глазами таблицу соответствия чисел. Например, как только мы видим 017, то можем представить в уме, как последние четыре бита ячейки памяти забиты единицами.
Теперь вернемся к поразрядным операциям и посмотрим как работает каждая из них. Для этого напишем небольшую программу:
int a, b; a = 017; b = 036; printf("0%o & 0%o = 0%o\n", a, b, a & b); printf("0%o | 0%o = 0%o\n", a, b, a | b); printf("0%o ^ 0%o = 0%o\n", a, b, a ^ b); printf("0%o \n", a, a 2); printf("0%o >> 2 = 0%o\n", a, a >> 2); printf("~0%o = 0%o\n", a, ~a);
Результат ее работы будет выглядеть так:
017 & 036 = 016 017 | 036 = 037 017 ^ 036 = 021 017 > 2 = 03 ~017 = 037777777760
Этот результат будет проще понять с помощью рисунка:

В последнем случае получилось такое большое число потому, что под форматы вывода целых чисел ( %d , %o , %X ) выделяется по 4 байта.
Теперь рассмотрим пример использования битовых операций. Допустим, у нас есть массив, требуется снять с него «маску», которая бы отражала, в какой позиции стоят отрицательные, а в какой положительные элементы. Пусть единица в бите обозначает соответствующий ей положительный элемент массива, а ноль — отрицательный. Так «битовая маска» массива будет выглядеть как 101110, или в восьмеричном представлении как 056. Составим алгоритм решения этой задачи:
- Будем считать, что массив состоит не более чем из 32 элементов. Поэтому для хранения его «маски» достаточно переменной типа int . Назовем ее mask и присвоим значение 0.
- Переберем элементы массива в цикле for . Если встречается положительный элемент, то установим соответствующий ему бит значения mask в 1.
- Выведем значение переменной mask на экран в виде восьмеричного числа.
Вроде бы все просто, но как установить в единицу определенный бит числа? Существует закономерность соответствия степеней двойки и двоичного представления числа:
2 0 = 0000 0001
2 1 = 0000 0010
2 2 = 0000 0100
2 3 = 0000 1000
2 4 = 0001 0000
и т.д. Теперь если применить к mask побитовую операцию | (ИЛИ), а в качестве второго операнда использовать определенную степень двойки, то один бит будет установлен в 1. Например:
(0) 0000 0000 | (2 5 ) 0010 0000 = 0010 0000
(32) 0010 0000 | (2 7 ) 1000 0000 = 1010 0000
При переборе первый элемент массива имеет индекс 0, но соответствующий ему бит в maskдолжен стоять впереди остальных. Если известно общее количество элементов массива (N), то можно определить степень двойки по формуле N — i — 1 . Так, имея четвертый положительный элемент массива (его индекс 3) из 10 элементов, следует установить в единицу седьмой с конца бит (он же будет четвертым с начала), а это значит надо использовать вторым операндом битового ИЛИ 2 6 , а 6 как раз будет 10( N ) — 3( i ) — 1.
Другая проблема — как в языке C возвести число в степень. Понятно, что можно написать свой код, но скорее всего в стандартной библиотеке уже есть подобная функция. С помощью заголовочного файла math.h можно подключить библиотеку с математическими функциями. Среди них есть функция pow() , которая принимает два числа и возвращает результат возведения первого числа в степень, выраженную вторым числом. Однако результат возвращается в виде вещественного числа, а нам требуется целое. Как быть? В Си есть операции приведения типов, которые меняют тип значения с одного на другой. Например, чтобы преобразовать значение вещественной переменной a в целое, следует написать (int) a .
Вот как может выглядеть вышеописанная программа:
#include #include #define N 12 int main() { int nums[N] = {7, 3, 9, -5, -3, 2, 1, 0, 16, -4, 2, 0}; int mask = 0; for (int i = 0; i N; i++) if (nums[i] >= 0) mask = mask | (int) pow(2, N-i-1); printf("%o\n", mask); }
Если у вас не получается скомпилировать программу, добавьте в конце вызова gcc опцию -lm (например, gcc -o bits bits.c -lm ).
Курс с решением задач:
pdf-версия
Как сделать вывод чисел в двоичной системе счисления?
Как сделать вывод чисел в двоичной системе счисления?
Есть вектор с большим количеством чисел разной длинны. Необходимо их вывести в двоичной системе исчисления.
Был вариант с std::bitset, но там используется константа. Видел boost::dynamic_bitset, но это не stl
- Вопрос задан более трёх лет назад
- 645 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 1

При помощи либы fmt, вывод в двоичной системе очень прост:
fmt::print(«», num);
Если без либ, то можно написать функцию, которая выводит число в двоичной в 2 цикла. Первым циклом найти позицию самой старшей единицы, вторым циклом вывести двоичные цифры от найденной старшей вниз до нулевой.
C#: Как число представить в двоичном виде?

Запись опубликована в рубрике C#, Вопрос-ответ. Добавьте в закладки постоянную ссылку.
Поделись с друзьями!
Language
Поиск
Поиск Google для разработчиков

Категории
- 1С (13)
- C# (72)
- C# Windows Phone (2)
- C++ (1)
- HTML (6)
- JavaScript (32)
- MySQL (1)
- PHP (48)
- Вопрос-ответ (27)
- Другие языки и технологии (4)
- Интересные моменты (2)
- Обзоры (2)
- Проще говоря (17)
- Учебное пособие C# (5)
Меня читает весь мир
Статистика и кнопочки
А так же
Метки
2011-2024 © Маматов Андрей
Использование материалов с данного сайта разрешено при указании прямой ссылки на страницу с ним. По вопросам сотрудничества или просто вопросам писать сюда или ВКонтакте.
Вывод двоичного числа в СИ
@avp без преобразования возможно вывести в этом чудесном языке? или нужно каждый символ обрабатывать и выводить?
12 фев 2019 в 17:46
0010 не является двоичным числом в синтаксисе Си
12 фев 2019 в 17:46
printf(«%s», «0010»); , не?
12 фев 2019 в 17:49
@Qada: Для утилитарных целей место двоичного вывода в языке С занял шестнадцатеричный вывод. Если вам все это нужно «для дела», то пользуйтесь шестнадцатеричным. Если же вам нужен именно двоичный (ибо «задание такое»), то да — «каждый символ обрабатывать и выводить».
12 фев 2019 в 18:09
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вы даете printf восьмеричное число 10 и просите напечатать его как десятичное. Вам выводится 8 — вы ждали чего-то другого?
Не существует спецификации формата для вывода двоичных чисел, поэтому их надо выводить вручную. В качестве примера:
// Вывод байта в двоичном виде typedef unsigned char byte; int main() < byte b = 93; // Или любое другое for (int i = 0; i < 8; i++) < printf("%c", (b & 0x80) ? '1' : '0'); b printf("\n"); return 0; >
Отслеживать
ответ дан 12 фев 2019 в 18:44
4,894 8 8 золотых знаков 15 15 серебряных знаков 29 29 бронзовых знаков
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Вывод двоичного числа в СИ
@avp без преобразования возможно вывести в этом чудесном языке? или нужно каждый символ обрабатывать и выводить?
12 фев 2019 в 17:46
0010 не является двоичным числом в синтаксисе Си
12 фев 2019 в 17:46
printf(«%s», «0010»); , не?
12 фев 2019 в 17:49
@Qada: Для утилитарных целей место двоичного вывода в языке С занял шестнадцатеричный вывод. Если вам все это нужно «для дела», то пользуйтесь шестнадцатеричным. Если же вам нужен именно двоичный (ибо «задание такое»), то да — «каждый символ обрабатывать и выводить».
12 фев 2019 в 18:09
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вы даете printf восьмеричное число 10 и просите напечатать его как десятичное. Вам выводится 8 — вы ждали чего-то другого?
Не существует спецификации формата для вывода двоичных чисел, поэтому их надо выводить вручную. В качестве примера:
// Вывод байта в двоичном виде typedef unsigned char byte; int main() < byte b = 93; // Или любое другое for (int i = 0; i < 8; i++) < printf("%c", (b & 0x80) ? '1' : '0'); b printf("\n"); return 0; >
Отслеживать
ответ дан 12 фев 2019 в 18:44
4,894 8 8 золотых знаков 15 15 серебряных знаков 29 29 бронзовых знаков
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Как вывести число в двоичной системе c
Форумчанин
Регистрация: 18.04.2009
Сообщений: 688
как вывести число в двоичной форме?
как вывести число в двоичной форме?
среда: vc
я прочёл МСДН, но так тока увидел cout cout про двоичную ничё
Форумчанин
Регистрация: 18.04.2009
Сообщений: 688
// TObase64.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include using namespace std; int _tmain(int argc, _TCHAR* argv[]) < short a; a = 6; ~a;//не работает. почему не знаю((((( поскажите плиз coutslength = 8 - slength; for (int i = 0; i
почему-то не работает ~a
Как сделать вывод чисел в двоичной системе счисления?
Как сделать вывод чисел в двоичной системе счисления?
Есть вектор с большим количеством чисел разной длинны. Необходимо их вывести в двоичной системе исчисления.
Был вариант с std::bitset, но там используется константа. Видел boost::dynamic_bitset, но это не stl
- Вопрос задан более трёх лет назад
- 645 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 1

При помощи либы fmt, вывод в двоичной системе очень прост:
fmt::print("", num);
Если без либ, то можно написать функцию, которая выводит число в двоичной в 2 цикла. Первым циклом найти позицию самой старшей единицы, вторым циклом вывести двоичные цифры от найденной старшей вниз до нулевой.
C#: Как число представить в двоичном виде?

Запись опубликована в рубрике C#, Вопрос-ответ. Добавьте в закладки постоянную ссылку.
Поделись с друзьями!
Language
Поиск
Поиск Google для разработчиков

Категории
- 1С (13)
- C# (72)
- C# Windows Phone (2)
- C++ (1)
- HTML (6)
- JavaScript (32)
- MySQL (1)
- PHP (48)
- Вопрос-ответ (27)
- Другие языки и технологии (4)
- Интересные моменты (2)
- Обзоры (2)
- Проще говоря (17)
- Учебное пособие C# (5)
Меня читает весь мир
Статистика и кнопочки
А так же
Метки
2011-2024 © Маматов Андрей
Использование материалов с данного сайта разрешено при указании прямой ссылки на страницу с ним. По вопросам сотрудничества или просто вопросам писать сюда или ВКонтакте.