Перейти к основному содержимому

Побитовые операции

Побитовые операции — это низкоуровневые операции, которые позволяют работать с данными на уровне их двоичного представления. В основе работы с ними лежит структура двоичного числа: самый крайний бит справа считается младшим (он имеет индекс 0 и наименьший вес), а по мере движения влево следуют старшие биты. Важной характеристикой является битовая длина — она показывает количество битов, необходимых для хранения значения, и вычисляется как индекс самого старшего установленного бита плюс один.

Например, в числе 0b101 (десятичное значение 5) крайняя правая единица — это бит с индексом 0, а крайняя левая единица — бит с индексом 2. Его битовая длина равна 3.

На практике отдельные биты часто используются как автономные переключатели состояний, называемые флагами. Чтобы проверять, устанавливать или сбрасывать такие флаги, не затрагивая остальную часть числа, используются битовые маски — специальные шаблоны, которые работают как фильтры для выделения нужных битов.

Например, пусть некоторое значение настроек задано числом 0b1010, где второй бит справа (индекс 1) отвечает за запись. Чтобы проверить этот флаг, нужно использовать маску 0b0010: она обнулит все остальные биты и оставит только искомый бит. Такой подход широко применяется в криптографии, сетевых протоколах, алгоритмах сжатия и оптимизации производительности, где требуется точный контроль над данными (см. пример операции И в разделе логические операции).

Для работы с побитовыми операциями в языке «1С:Элемент» предусмотрены типы:

  • ПобитовыеОперации — содержит методы для выполнения операций над целыми числами и байтовыми последовательностями,
  • МассивБитов — представляет собой изменяемую последовательность битов для хранения и работы с бинарными данными.

Тип «ПобитовыеОперации»​

ПобитовыеОперации — тип-одиночка, предназначен для выполнения низкоуровневых операций над целыми числами и байтовыми последовательностями. Этот тип позволяет работать с отдельными битами данных, что необходимо при решении задач, требующих точного контроля над двоичным представлением информации.

Логические операции​

Логические побитовые операции позволяют выполнять стандартные логические действия на уровне отдельных битов. Базовым набором методов являются логические побитовые операции — это И, Или, ИсключающееИли, Не и ИНе.

Ниже приведены таблицы истинности для базовых операций (для каждого отдельного бита):

Бит AБит BИ (AND)Или (OR)ИсключающееИли (XOR)ИНе (AND-NOT)
000000
010110
100111
111100

Операция ИНе часто используется для сброса битов, так как она возвращает 1 только если бит в числе A равен 1, а соответствующий бит в числе B равен 0.

Операция Не инвертирует значение единственного операнда:

Бит AНе (NOT)
01
10

Например, операция И может использоваться для маскирования определенных битов, чтобы извлечь из числа только нужную часть информации.

метод ИзвлечьФлагиДоступа(): Число
знч Права = 0b11010111 // Полные права пользователя
знч МаскаФайл = 0b00000111 // Маска для получения прав на чтение, запись, выполнение файлов
возврат ПобитовыеОперации.И(Права, МаскаФайл) // Получаем только нужные права
;

Операция Или применяется для установки определенных битов в единицу, например, для комбинирования флагов доступа.

метод УстановитьНесколькоФлагов(): Число
знч БазовыеПрава = 0b10000000 // Базовые права
знч ДопПрава = 0b00001100 // Дополнительные права (чтение + запись)
возврат ПобитовыеОперации.Или(БазовыеПрава, ДопПрава) // Комбинируем права
;

Операция ИсключающееИли полезна для переключения состояния битов или простого шифрования данных.

метод ПереключитьФлаг(): Число
знч Настройки = 0b10101010 // Текущие настройки
знч ФлагОтладки = 0b00000001 // Флаг отладки
возврат ПобитовыеОперации.ИсключающееИли(Настройки, ФлагОтладки) // Переключаем отладку
;

Операция Не инвертирует все биты числа, что может быть полезно при создании инвертированных битовых масок.

метод СоздатьИнвертированнуюМаску(): Число
знч Маска = 0b00001111 // Исходная маска
// для типа Число результатом будет отрицательное значение -> -16
возврат ПобитовыеОперации.Не(Маска) // Инвертируем маску
;

Операция ИНе выполняет операцию И с инвертированным вторым операндом, что удобно для сброса определенных битов.

метод СброситьФлаг(): Число
знч Права = 0b11111111 // Все права предоставлены
знч ЗапретЗаписи = 0b00000010 // Флаг записи
возврат ПобитовыеОперации.ИНе(Права, ЗапретЗаписи) // Отбираем право на запись
;

Все эти операции создают новые экземпляры данных, сохраняя исходные значения неизменными.

Проверки по битам​

Методы проверки по битам позволяют анализировать состояние отдельных битов и групп битов в данных. Они широко применяются при работе с флагами и настройками, а также для верификации бинарных структур. Эти методы обеспечивают эффективный способ контроля и анализа битовых данных без необходимости ручного разбора двоичного представления.

Метод Получить() удобен для проверки состояния отдельных флагов в битовом поле.

метод ПроверитьПравоНаЧтение(): Булево
знч Права = 0b11010101 // Бит чтения (позиция 0) установлен
возврат ПобитовыеОперации.Получить(Права, 0) // Проверяем право на чтение: Истина
;

Метод ПроверитьПоБитовойМаске() используется для верификации наличия нескольких флагов одновременно.

метод ПроверитьПраваАдминистратора(): Булево
знч ПользовательскиеПрава = 0b11110000 // Права пользователя
знч МаскаАдминистратора = 0b11100000 // Маска административных прав
возврат ПобитовыеОперации.ПроверитьПоБитовойМаске(ПользовательскиеПрава, МаскаАдминистратора)
;

Метод БитоваяДлина() помогает определить количество битов для хранения значения.

метод ОпределитьРазмерПоля(): Число
знч Идентификатор = 1023 // Значение идентификатора
возврат ПобитовыеОперации.БитоваяДлина(Идентификатор) // Минимальное количество битов: 10
;

Операции сдвига​

Операции сдвига позволяют эффективно умножать или делить числа на степени двойки, а также позиционировать биты в данных. Сдвиг влево на N разрядов эквивалентен умножению на 2 в степени N и часто используется для быстрого масштабирования значений. Арифметический сдвиг вправо сохраняет знак числа, дублируя знаковый бит при сдвиге, тогда как логический сдвиг всегда заполняет освободившиеся разряды нулями. Эти операции находят применение в алгоритмах сжатия данных, криптографических преобразованиях и оптимизации арифметических вычислений.

Метод СдвигВлево() используется для быстрого умножения на степени двойки.

метод БыстроеУмножение(): Число
знч Значение = 5
знч Степень = 3
возврат ПобитовыеОперации.СдвигВлево(Значение, Степень) // 5 * 2^3 = 40
;

Метод АрифметическийСдвигВправо() выполняет деление с сохранением знака, заполняя старшие биты значением знакового разряда.

метод БезопасноеДелениеОтрицательного(): Число
знч Значение = -20 // 11101100
знч Сдвиг = 2

// Арифметический сдвиг вправо делит число на 2^2 (-20 / 4 = -5)
// и заполняет освободившиеся старшие биты единицами: 11101100 -> 11111011
возврат ПобитовыеОперации.АрифметическийСдвигВправо(Значение, Сдвиг) // Результат: -5
;

Управление отдельными битами​

Методы управления отдельными битами предоставляют точечный контроль над состоянием битов в данных. Они позволяют гибко работать с флагами, настройками и другими бинарными структурами данных. Эти операции особенно полезны при работе с битовыми полями структур данных и системами управления правами доступа.

Метод Установить() позволяет принудительно активировать или деактивировать определенный бит по индексу.

метод УстановитьФлагОтладки(): Число
знч Настройки = 0b10101010
знч ИндексФлага = 2
// Устанавливаем 2-й бит в 1: 0b10101110
возврат ПобитовыеОперации.Установить(Настройки, ИндексФлага, Истина)
;

Метод ИнвертироватьБит() меняет значение бита на противоположное.

метод ПереключитьРежим(): Число
знч Режим = 0b11110000
знч БитРежима = 3
возврат ПобитовыеОперации.ИнвертироватьБит(Режим, БитРежима) // 0b11111000
;

Тип «МассивБитов»​

Тип МассивБитов представляет собой изменяемую последовательность битов, предназначенную для эффективной работы с бинарными данными. В отличие от скалярных побитовых операций, массив битов позволяет работать с последовательностями произвольной длины, сохраняя структуру и обеспечивая удобный доступ к отдельным битам.

Создание и базовые операции​

Массив битов можно создать несколькими способами: пустым, с заданным начальным размером и значением, либо преобразовав существующие данные из чисел или байтов. После создания массив предоставляет прямой доступ к отдельным битам через индексы массива (где индекс 0 соответствует младшему биту), а также методы для очистки содержимого и изменения размера.

метод СоздатьМассивБитов(): МассивБитов
// Создаем массив размером 8 бит, все биты установлены
знч Массив = новый МассивБитов(8, Истина)
// Сбрасываем первый бит (индекс 0)
Массив[0] = Ложь
возврат Массив // Бинарное представление: "11111110"
;

метод ПреобразоватьИзЧисла(): МассивБитов
знч Число = 42 // 0b00101010
// Создаем массив из числа с фиксированным размером 8 бит
знч Массив = МассивБитов.ИзЧисла(Число, 8)
возврат Массив // Бинарное представление: "00101010"
;

Пакетные операции над битами​

Массив битов предоставляет удобные методы для работы с группами битов сразу. Можно устанавливать, проверять и инвертировать диапазоны битов, а также выполнять поиск установленных или сброшенных битов. Это особенно полезно при работе с битовыми картами, флагами и другими структурами данных.

метод ИнвертироватьБитыМассива(): МассивБитов
знч Массив = новый МассивБитов(16)
// Устанавливаем биты в диапазоне [4, 8) (индексы 4, 5, 6, 7)
Массив.УстановитьБиты(4, 8, Истина)
// Инвертируем биты в диапазоне [0, 4) (индексы 0, 1, 2, 3)
Массив.ИнвертироватьБиты(0, 4)
возврат Массив
;
метод НайтиИндексБита(): Число
// Используем число, где биты 0, 2, 4, 6, 8 установлены (0b0101010101)
знч Массив = МассивБитов.ИзЧисла(0b0101010101)
// Находим первый установленный бит, начиная с индекса 3
// Индексы: 0(1), 1(0), 2(1), 3(0), 4(1) -> Результат 4
знч Индекс = Массив.СледующийУстановленныйБит(3)
возврат Индекс // 4
;

Побитовые операции и преобразования​

Массив битов поддерживает все стандартные побитовые операции, аналогично скалярным типам, но с возможностью работы с данными произвольной длины. Доступны различные виды сдвигов, включая циклические, что расширяет возможности работы с данными. Массив также можно преобразовать обратно в число или байты для дальнейшей работы.

метод ПобитовыеОперации(): МассивБитов
знч Массив1 = МассивБитов.ИзЧисла(0b11110000, 8)
знч Массив2 = МассивБитов.ИзЧисла(0b00111100, 8)
// Выполняем операцию И (результат сохраняется в Массив1)
Массив1.ПобитовоеИ(Массив2)
возврат Массив1 // "00110000"
;
метод ПреобразованиеДанных(): Число
знч Массив = новый МассивБитов(8)
// Устанавливаем биты в диапазоне [2, 6) -> индексы 2, 3, 4, 5
Массив.УстановитьБиты(2, 6, Истина)
// Преобразуем обратно в число (00111100 = 60)
знч Результат = Массив.ВЧисло()
возврат Результат // 60
;