Приходилось ли вам когда-нибудь использовать битовый сдвиг в реальных проектах?


84

Приходилось ли вам когда-нибудь использовать битовый сдвиг в реальных проектах программирования? В большинстве (если не во всех) языках высокого уровня есть операторы сдвига, но когда вам действительно нужно их использовать?

Ответы:


58

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

Также вам нужны сдвиги для генерации хэшей. Полиномиальная арифметика (CRC, коды Рида-Соломона - основные приложения) или также использует сдвиги.

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

Компиляторы выявляют случаи, когда умножение сводится к сдвигу.


37

Да, я использовал их много раз. Битовое вращение важно для встроенного оборудования, где битовые маски очень распространены. Это также важно в программировании игр, когда вам нужна максимальная производительность.

Изменить: Кроме того, я часто использую их для управления растровыми изображениями, например, для изменения глубины цвета или преобразования RGB <-> BGR.


Прикомандированный. Я много занимаюсь встроенным программированием, и смещение битов - обычная операция.
e.James 06

Преобразования RGB <-> BGR здесь.
Neil N

25
  • Создание хороших значений флагов для перечислений (вместо того, чтобы вводить вручную 1, 2, 4 ...)
  • Распаковка данных из битовых полей (их используют многие сетевые протоколы)
  • Обход Z-кривой
  • Хаки производительности

И я не могу вспомнить много случаев, когда они используются. Обычно бывает наоборот - есть какая-то конкретная проблема, и оказывается, что использование битовых операций дает лучшие результаты (обычно с точки зрения производительности - времени и / или пространства).


Возможно, вам понадобится сохранить, например, два shorts в одном intполе eger в состоянии сеанса в ASP.net без накладных расходов на чтение и блокировку сеанса для чтения двух отдельных значений. Также сохраняются накладные расходы памяти на сохранение двух значений в сеансе.
Дэвид д Си Фрейтас

15

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


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


7

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

Например:

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

не могли бы вы опубликовать пример того, как вы используете его, чтобы найти куб или квадратный корень? Я немного не понимаю, как это можно сделать.
Xsmael

5

Да, все же это нужно.

Например, здесь, в моей работе, мы разрабатываем программное обеспечение для связи с ПЛК через последовательный порт COMx. Необходимо обрабатывать биты внутри байта, мы используем сдвиг влево / вправо и логические операторы OR, XOR, AND день за днем.

Например, предположим, что нам нужно включить бит 3 (справа налево) байта:

Гораздо эффективнее:

Byte B;

B := B XOR 4;

Вместо:

Byte B = 0;
String s;  // 0 based index

s = ConvertToBinary (B);
s[5] = "1";
B := ConvertToDecimal (s);

С уважением.


1
Вы можете добавить, почему 4 относится к биту 3 (справа налево)
HCP

1
Почему s [5]? Разве это не должно быть S [2]?
IamIC 05

1
B: = B XOR 4; В этом случае, чтобы включить определенный бит, не должно ли это быть просто ИЛИ? Разве XOR не используется для переключения? stackoverflow.com/questions/47981/…
Хари

4

Когда я писал на ассемблере, мой код был полон битового сдвига и маскировки.

И в C тоже.

Я не очень много работал с JavaScript или серверными языками.

Вероятно, лучшее современное использование - это пошаговый обход упакованного массива логических значений, представленных как единицы и нули. Раньше я всегда сдвигал влево и проверял знаковый бит в сборке, но на языках более высокого уровня вы сравниваете со значением.

Например, если у вас 8 бит, вы проверяете верхний бит с помощью «if (a> 127) {...}». Затем вы оставили сдвиг (или умножили на 2), произвели «и» с 127 (или сделали вычитание 256, если был установлен последний бит), и повторите это снова.


3

Я часто использовал их при сжатии / распаковке изображений, когда биты в растровом изображении были сжаты. Используя http://en.wikipedia.org/wiki/Huffman_coding , сжимаемые вещи состоят из разного количества бит (они не все выровнены по байтам), и поэтому вам необходимо сдвинуть их по битам при их кодировании или декодировании. .


3

Например, в реализации криптографических методов на таких языках, как C, C ++. Бинарные файлы, алгоритмы сжатия и операции с логическими списками - побитовая операция всегда хороша =)


3

Битовый сдвиг не решает проблемы программирования высокого уровня, но иногда нам приходится решать проблемы более низкого уровня, и для этого удобно не писать отдельную библиотеку на C. Я предполагаю, что именно тогда он чаще всего используется.

Я лично использовал его при написании кодировщика для преобразователя набора символов EBCDIC .


3

Да. Как вы могли догадаться, это, скорее всего, можно найти в низкоуровневом программировании, например, при разработке драйверов устройств. Но я работал над проектом C #, где мне нужно было разработать веб-сервис, который получал данные от медицинских устройств. Все двоичные данные, хранящиеся на устройстве, были закодированы в пакеты SOAP, но двоичные данные были сжаты и закодированы. Поэтому, чтобы распаковать его, вам придется проделать множество битовых манипуляций. И, кроме того, вам придется выполнять много битов смещения, чтобы проанализировать любую полезную информацию, например, серийный номер устройства - это младшая половина второго байта или что-то в этом роде. Также я видел, как некоторые люди в мире .NET (C #) использовали битовую маскировку и атрибут флага, лично у меня никогда не было желания это делать.


3

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

Они также полезны при использовании целых чисел и т. Д. Для отслеживания статусов.



3

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


3

Сдвиг битов часто используется при расшифровке протоколов онлайн-игр. Протоколы предназначены для использования небольшой полосы пропускания, насколько это возможно, поэтому вместо передачи количества игроков на сервере, имен и т. Д. В int32, вся информация упаковывается в как можно меньшее количество байтов. В наши дни, когда большинство людей используют широкополосный доступ, в этом нет особой необходимости, но когда они были изначально разработаны, люди использовали модемы 56k для игр, так что каждый бит имел значение.

Наиболее яркими примерами этого являются многопользовательские игры Valve, особенно Counter-Strike, Counter-Strike Source. Протокол Quake3 тоже такой же, но Unreal не такой уж тонкий.

Вот пример (.NET 1.1)

string data = Encoding.Default.GetString(receive);

if ( data != "" )
{
    // If first byte is 254 then we have multiple packets
    if ( (byte) data[0] == 254 )
    {
        // High order contains count, low order index
        packetCount = ((byte) data[8]) & 15; // indexed from 0
        packetIndex = ((byte) data[8]) >> 4;
        packetCount -= 1;

        packets[packetIndex] = data.Remove(0,9);
    }
    else
    {
        packets[0] = data;

    }
}

Конечно, рассматриваете ли вы это как настоящий проект или просто как хобби (на C #) - решать вам.



2

Найдите ближайшую степень двойки, большую или равную данному числу:

1 << (int)(ceil(log2(given)))

Требуется для текстурирования на оборудовании, не поддерживающем произвольные размеры текстур.


2

Еще одна очень распространенная вещь - это сдвиг на 4 бита при извлечении старшего полубайта байта, т.е.

#define HIGH_NIBBLE(byte) (((byte) >> 4) & 0x0F)
#define LOW_NIBBLE(byte)  ( (byte)       & 0x0F)

Это особенно актуально, если вы работаете напрямую с оборудованием, получая данные непосредственно из регистров с произвольными битовыми отображениями.
Крис

1

Да, использовал их в парсере транспортного потока MPEG2-2. Это было проще и лучше читалось.


1

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


1

Я видел побитовые операторы, используемые, когда в качестве параметра свойства использовалось несколько флагов. Например, число 4 = 1 0 0 означает, что установлен один из трех флагов. Это не очень хорошо для общедоступного API, но в особых случаях может ускорить работу, поскольку проверка битов выполняется быстро.


1

Каждый битблтер, который я когда-либо писал, не мог быть завершен без возможности сдвигать биты влево и вправо.


1

Я использовал их в играх для упаковки группы флагов в один байт / символ для сохранения на карту данных. Такие вещи, как сохранение статуса разблокируемых объектов и т. Д. В настоящее время не так уж и необходимы, но могут сэкономить работу.


1

Я использую его в проекте для встроенной системы, которая должна считывать данные EDID монитора. Некоторые данные в EDID кодируются следующим образом:

Байт № 3:
Горизонтальное гашение - младшие 8 бит
Байт № 4:
Нижний полубайт: Горизонтальное гашение - старшие 4 бита
Верхний полубайт : что-то еще

1

Да, при выполнении двоичной связи между приложениями Java и C # одно - с прямым порядком байтов, а другое - с прямым порядком байтов (не обязательно в этом порядке). Я создал класс InputStream, который мог читать числа с другим порядком байтов, и для работы он использовал смещение байтов.

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


0

Сдвиг битов также требуется при обмене данными с оборудованием «нижнего уровня», например, с цифровыми блоками ввода-вывода Ethernet или ПЛК, которые обычно упаковывают отдельные значения ввода / вывода в байты.


0

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

http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/


0

Да все время. Как эти макросы для упаковки и распаковки 3-пространственной координаты в / из 32-битного целого числа:

#define Top_Code(a, b, c)           ((((a) + x) << 20) | (((b) + y) << 10) | ((c) + z))                           
#define From_Top_Code(a, b, c, f)   (a = (((f) >>> 20) - x), b = ((((f) & 0xffc00) >>> 10) - y), c = (((f) & 0x3ff) - z))        

0

Однажды (много-много лет назад) я написал процедуру вывода для проекта, который создавал электронные таблицы Excel с использованием структуры Excel Oper. Это был формат двоичного файла, который требовал большого количества битрейта. Следующая ссылка дает представление о структуре Safari Books .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.