Когда использовать операторы Shift << >> в C #? - PullRequest
29 голосов
/ 19 декабря 2009

Я изучал операторы сдвига в C #, пытаясь выяснить, когда использовать их в моем коде.

Я нашел ответ, но для Java вы могли бы:

a) Сделать быстрее Операции умножения и деления целых чисел:

* 4839534 * 4 * можно сделать так: 4839534 << 2 </em>

или

543894/2 можно сделать так: 543894 >> 1

Сдвигать операции намного быстрее, чем умножение для большинства процессоров.

b) Сборка байтовых потоков до значений int

c) Для ускорения операций с графикой, поскольку красный, зеленый и синий цвета кодируются отдельными байтами.

d) Упаковка небольших чисел в одну длинную ...


Для b, c и d я не могу представить здесь настоящий образец.

Кто-нибудь знает, можем ли мы выполнить все эти задачи в C #? Есть ли более практическое применение для операторов сдвига в C #?

Ответы [ 4 ]

38 голосов
/ 19 декабря 2009

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

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

17 голосов
/ 19 декабря 2009

Если нет очень веской причины, мое мнение таково, что использование таких хитрых трюков, как правило, просто создает более запутанный код с небольшой добавленной стоимостью. Авторы компиляторов - умная группа разработчиков и знают гораздо больше об этих хитростях, чем обычный программист. Например, деление целого числа на степень 2 быстрее с оператором сдвига, чем деление, но, вероятно, в этом нет необходимости, поскольку компилятор сделает это за вас. Это можно увидеть, посмотрев сборку, в которой компилятор Microsoft C / C ++ и gcc выполняют эти оптимизации.

15 голосов
/ 04 июня 2014

Я поделюсь интересным использованием, с которым я сталкивался в прошлом. Этот пример бесстыдно скопирован из дополнительного ответа на вопрос: « Что означает атрибут Enum [Flags] в C #? »

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3
}

Это может быть легче расширить, чем записывать буквальные 1, 2, 4, 8, ... значения, особенно когда вы пройдете 17 флагов.

Компромисс: если вам нужно более 31 флага (1 << 30), вам также нужно быть осторожным, указав свой enum как нечто с более высокой верхней границей, чем целое число со знаком (объявив его public enum MyEnum : ulong например, который даст вам до 64 флагов). Это потому что ...

1 << 29 == 536870912
1 << 30 == 1073741824
1 << 31 == -2147483648
1 << 32 == 1
1 << 33 == 2

Напротив, если вы установите значение enum непосредственно в 2147483648, компилятор выдаст ошибку.

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

[Flags]
public enum MyEnum : ulong
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3,

    // Compiler error:
    // Constant value '-2147483648' cannot be converted to a 'ulong'
    // (Note this wouldn't be thrown if MyEnum derived from long)
    ThirtySecond = 1 << 31,

    // so what you would have to do instead is...
    ThirtySecond = 1UL << 31,
    ThirtyThird  = 1UL << 32,
    ThirtyFourth = 1UL << 33
}
6 голосов
/ 19 декабря 2009

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

Операторы смены сегодня редко встречаются в бизнес-приложениях. Они часто появляются в низкоуровневом коде, который взаимодействует с оборудованием или манипулирует упакованными данными. Они были более распространены во времена сегментов памяти 64 КБ.

...