Приходилось ли вам когда-нибудь использовать битовый сдвиг в реальных проектах программирования? В большинстве (если не во всех) языках высокого уровня есть операторы сдвига, но когда вам действительно нужно их использовать?
Приходилось ли вам когда-нибудь использовать битовый сдвиг в реальных проектах программирования? В большинстве (если не во всех) языках высокого уровня есть операторы сдвига, но когда вам действительно нужно их использовать?
Ответы:
Я все еще пишу код для систем, которые не имеют аппаратной поддержки с плавающей запятой. В этих системах сдвиг битов необходим почти для всех ваших арифметических операций.
Также вам нужны сдвиги для генерации хэшей. Полиномиальная арифметика (CRC, коды Рида-Соломона - основные приложения) или также использует сдвиги.
Однако сдвиги используются просто потому, что они удобны и точно выражают то, что задумал автор. Вы можете эмулировать все битовые сдвиги с умножением, если хотите, но это будет сложнее написать, менее читабельно и иногда медленнее.
Компиляторы выявляют случаи, когда умножение сводится к сдвигу.
Да, я использовал их много раз. Битовое вращение важно для встроенного оборудования, где битовые маски очень распространены. Это также важно в программировании игр, когда вам нужна максимальная производительность.
Изменить: Кроме того, я часто использую их для управления растровыми изображениями, например, для изменения глубины цвета или преобразования RGB <-> BGR.
И я не могу вспомнить много случаев, когда они используются. Обычно бывает наоборот - есть какая-то конкретная проблема, и оказывается, что использование битовых операций дает лучшие результаты (обычно с точки зрения производительности - времени и / или пространства).
short
s в одном int
поле eger в состоянии сеанса в ASP.net без накладных расходов на чтение и блокировку сеанса для чтения двух отдельных значений. Также сохраняются накладные расходы памяти на сохранение двух значений в сеансе.
Одно место, где я использую их все время, - это транспонирование порядка байтов целых чисел для кросс-платформенных приложений. Они также иногда могут быть полезны (наряду с другими операторами обработки битов) при копировании 2D-графики.
Я использовал их несколько раз, но почти всегда для анализа двоичного формата файла.
Битовые сдвиги выполняются быстро. Они были реализованы в наборах команд ЦП задолго до операций деления и модуля. Многие из нас использовали битовые сдвиги для арифметических операций, которые просты на бумаге и карандаше, но недоступны на наших процессорах.
Например:
Да, все же это нужно.
Например, здесь, в моей работе, мы разрабатываем программное обеспечение для связи с ПЛК через последовательный порт 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);
С уважением.
Когда я писал на ассемблере, мой код был полон битового сдвига и маскировки.
И в C тоже.
Я не очень много работал с JavaScript или серверными языками.
Вероятно, лучшее современное использование - это пошаговый обход упакованного массива логических значений, представленных как единицы и нули. Раньше я всегда сдвигал влево и проверял знаковый бит в сборке, но на языках более высокого уровня вы сравниваете со значением.
Например, если у вас 8 бит, вы проверяете верхний бит с помощью «if (a> 127) {...}». Затем вы оставили сдвиг (или умножили на 2), произвели «и» с 127 (или сделали вычитание 256, если был установлен последний бит), и повторите это снова.
Я часто использовал их при сжатии / распаковке изображений, когда биты в растровом изображении были сжаты. Используя http://en.wikipedia.org/wiki/Huffman_coding , сжимаемые вещи состоят из разного количества бит (они не все выровнены по байтам), и поэтому вам необходимо сдвинуть их по битам при их кодировании или декодировании. .
Битовый сдвиг не решает проблемы программирования высокого уровня, но иногда нам приходится решать проблемы более низкого уровня, и для этого удобно не писать отдельную библиотеку на C. Я предполагаю, что именно тогда он чаще всего используется.
Я лично использовал его при написании кодировщика для преобразователя набора символов EBCDIC .
Да. Как вы могли догадаться, это, скорее всего, можно найти в низкоуровневом программировании, например, при разработке драйверов устройств. Но я работал над проектом C #, где мне нужно было разработать веб-сервис, который получал данные от медицинских устройств. Все двоичные данные, хранящиеся на устройстве, были закодированы в пакеты SOAP, но двоичные данные были сжаты и закодированы. Поэтому, чтобы распаковать его, вам придется проделать множество битовых манипуляций. И, кроме того, вам придется выполнять много битов смещения, чтобы проанализировать любую полезную информацию, например, серийный номер устройства - это младшая половина второго байта или что-то в этом роде. Также я видел, как некоторые люди в мире .NET (C #) использовали битовую маскировку и атрибут флага, лично у меня никогда не было желания это делать.
При преобразовании чисел из прямого порядка байтов в формат прямого порядка байтов и наоборот
Я работаю на производителя компьютерной периферии. Я столкнулся и должен был реализовать код, который использует битовые сдвиги практически каждый день.
Сдвиг битов часто используется при расшифровке протоколов онлайн-игр. Протоколы предназначены для использования небольшой полосы пропускания, насколько это возможно, поэтому вместо передачи количества игроков на сервере, имен и т. Д. В 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 #) - решать вам.
Быстрое преобразование Фурье - БПФ и его метод Кули-Тьюки потребуют использования операций сдвига битов.
Еще одна очень распространенная вещь - это сдвиг на 4 бита при извлечении старшего полубайта байта, т.е.
#define HIGH_NIBBLE(byte) (((byte) >> 4) & 0x0F)
#define LOW_NIBBLE(byte) ( (byte) & 0x0F)
Мне пришлось написать программу для анализа файлов .ifo на DVD-дисках. Это поля, которые объясняют, сколько заголовков, глав, меню и т. Д. Находится на диске. Они состоят из упакованных битов всех размеров и ориентации. Я подозреваю, что многие двоичные форматы требуют аналогичного сдвига битов.
Я видел побитовые операторы, используемые, когда в качестве параметра свойства использовалось несколько флагов. Например, число 4 = 1 0 0 означает, что установлен один из трех флагов. Это не очень хорошо для общедоступного API, но в особых случаях может ускорить работу, поскольку проверка битов выполняется быстро.
Каждый битблтер, который я когда-либо писал, не мог быть завершен без возможности сдвигать биты влево и вправо.
Я использую его в проекте для встроенной системы, которая должна считывать данные EDID монитора. Некоторые данные в EDID кодируются следующим образом:
Байт № 3:
Горизонтальное гашение - младшие 8 бит
Байт № 4:
Нижний полубайт: Горизонтальное гашение - старшие 4 бита
Верхний полубайт : что-то еще
Да, при выполнении двоичной связи между приложениями Java и C # одно - с прямым порядком байтов, а другое - с прямым порядком байтов (не обязательно в этом порядке). Я создал класс InputStream, который мог читать числа с другим порядком байтов, и для работы он использовал смещение байтов.
Иногда также, когда вы хотите поместить 4 коротких строки в 4 байта длинной, это может быть случай использования байтового смещения. Я думаю, что сделал это много лет назад ...
Да, сдвиг битов постоянно используется во встроенном ПО низкого уровня. Его также можно использовать как почти волшебный трюк для выполнения чрезвычайно быстрых математических операций, взгляните на
http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/
Да все время. Как эти макросы для упаковки и распаковки 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))
Однажды (много-много лет назад) я написал процедуру вывода для проекта, который создавал электронные таблицы Excel с использованием структуры Excel Oper. Это был формат двоичного файла, который требовал большого количества битрейта. Следующая ссылка дает представление о структуре Safari Books .