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

84

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

Филип Мортон
источник

Ответы:

58

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

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

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

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

Нильс Пипенбринк
источник
37

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

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

оборота MrZebra
источник
Прикомандированный. Я много занимаюсь встроенным программированием, и смещение битов - обычная операция.
e.James 06
Преобразования RGB <-> BGR здесь.
Neil N
25
  • Создание хороших значений флагов для перечислений (вместо того, чтобы вводить вручную 1, 2, 4 ...)
  • Распаковка данных из битовых полей (их используют многие сетевые протоколы)
  • Обход Z-кривой
  • Хаки производительности

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

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

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

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

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

Дэвид Грант
источник
7

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

Например:

  • Я использовал битовые сдвиги для проектов, в которых учитывались основные факторы больших композитов.
  • Я также использовал битовые сдвиги для нахождения квадратного и кубического корня из произвольно больших целых чисел.
одиннадцать81
источник
не могли бы вы опубликовать пример того, как вы используете его, чтобы найти куб или квадратный корень? Я немного не понимаю, как это можно сделать.
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 , сжимаемые вещи состоят из разного количества бит (они не все выровнены по байтам), и поэтому вам необходимо сдвинуть их по битам при их кодировании или декодировании. .

ChrisW
источник
3

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

Антон
источник
3

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

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

Майкл Медоуз
источник
3

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

WebMatrix
источник
3

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

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

Кевин
источник
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

Быстрое преобразование Фурье - БПФ и его метод Кули-Тьюки потребуют использования операций сдвига битов.

ЛицензияQ
источник
Прокручиваете собственные процедуры БПФ? тут-тут :) Признаюсь, я тоже это сделал - отлично подходит для глубокого понимания алгоритма.
Марти
2

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

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

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

зул
источник
2

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

#define HIGH_NIBBLE(byte) (((byte) >> 4) & 0x0F)
#define LOW_NIBBLE(byte)  ( (byte)       & 0x0F)
Hlovdal
источник
Это особенно актуально, если вы работаете напрямую с оборудованием, получая данные непосредственно из регистров с произвольными битовыми отображениями.
Крис
1

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

RvdK
источник
1

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

Стив Роу
источник
1

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

Lycha
источник
1

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

Скотт Эвернден
источник
1

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

xan
источник
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 .

Австралиец Крейг
источник