Подтвердить что ты не робот

Что означают две левые угловые скобки "<<" в С#?

В основном вопросы в заголовке. Я смотрю исходный код MVC 2:

[Flags]
public enum HttpVerbs {
    Get = 1 << 0,
    Post = 1 << 1,
    Put = 1 << 2,
    Delete = 1 << 3,
    Head = 1 << 4
}

и мне просто интересно, что делает двойные левые угловые <<.

4b9b3361

Ответ 1

Это будет побитовый сдвиг влево.

Для каждого сдвига влево значение эффективно умножается на 2. Так, например, запись value << 3 будет умножать значение на 8.

То, что он действительно делает внутри, перемещает все фактические биты значения, оставленного на одном месте. Поэтому, если у вас есть значение 12 (десятичное), в двоичном формате это 00001100; смещение влево, одно место превратит это в 00011000, или 24.

Ответ 2

Когда вы пишете

1 << n

Вы смещаете битную комбинацию 000000001 на n раз слева и, таким образом, помещаете n в показатель степени 2:

2^n

Итак,

1 << 10

Действительно,

1024

В списке из 5 пунктов ваш for будет циклически повторяться 32 раза.

Ответ 3

Он называется оператором left-shift. Взгляните на документацию

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

Простой пример, демонстрирующий оператор left-shift:

for (int i = 0; i < 10; i++)
{
    var shiftedValue = 1 << i;
    Console.WriteLine(" 1 << {0} = {1} \t Binary: {2}",i,shiftedValue,Convert.ToString(shiftedValue,2).PadLeft(10,'0'));
}

//Output:

// 1 << 0 = 1      Binary: 0000000001
// 1 << 1 = 2      Binary: 0000000010
// 1 << 2 = 4      Binary: 0000000100
// 1 << 3 = 8      Binary: 0000001000
// 1 << 4 = 16     Binary: 0000010000
// 1 << 5 = 32     Binary: 0000100000
// 1 << 6 = 64     Binary: 0001000000
// 1 << 7 = 128    Binary: 0010000000
// 1 << 8 = 256    Binary: 0100000000
// 1 << 9 = 512    Binary: 1000000000

Перемещение одного бита влево эквивалентно множественному на два. Фактически, движущиеся биты быстрее, чем стандартное умножение. Давайте рассмотрим пример, демонстрирующий этот факт:

Скажем, мы имеем два метода:

static void ShiftBits(long number,int count)
{
    long value = number;
    for (int i = 0; i < count; i+=128)
    {
          for (int j = 1; j < 65; j++)
          {
              value = value << j;
          }
          for (int j = 1; j < 65; j++)
          {
               value = value >> j;
          }
    }
}

static void MultipleAndDivide(long number, int count)
{
      long value = number;
      for (int i = 0; i < count; i += 128)
      {
            for (int j = 1; j < 65; j++)
            {
                value = value * (2 * j);
            }
            for (int j = 1; j < 65; j++)
            {
                value = value / (2 * j);
            }
      }
}

И мы хотим протестировать их следующим образом:

ShiftBits(1, 10000000);
ShiftBits(1, 100000000);
ShiftBits(1, 1000000000);
...
MultipleAndDivide(1, 10000000);
MultipleAndDivide(1, 100000000);
MultipleAndDivide(1, 1000000000);
...

Вот результаты:

Bit manipulation 10.000.000 times: 58 milliseconds
Bit manipulation 100.000.000 times: 375 milliseconds
Bit manipulation 1.000.000.000 times: 4073 milliseconds

Multiplication and Division 10.000.000 times: 81 milliseconds
Multiplication and Division 100.000.000 times: 824 milliseconds
Multiplication and Division 1.000.000.000 times: 8224 milliseconds

Ответ 4

Это Побитовый сдвиг влево, он работает, сдвигая цифры двоичного эквивалента числа на заданные (правые) номера.

так:

temp = 14 << 2

двоичный эквивалент 14 - это 00001110, смещающий его 2 раза, означает толкание нуля с правой стороны и смещение каждой цифры на левую сторону, что делает ее 00111000 равной 56.

visual

В вашем примере:

i < (1 << list.Count)
  • 0000000001 = 1, если list.Count = 0 результат 0000000001 = 1
  • 0000000001 = 1, если list.Count = 1 результат 0000000010 = 2
  • 0000000001 = 1, если list.Count = 2 результат 0000000100 = 4
  • 0000000001 = 1, если list.Count = 3 результат 0000001000 = 8

и т.д. В общем случае он равен 2 ^ list.Count (2, поднятому до степени list.Count)

Ответ 5

Чтобы оператор left bithift. Он сдвигает бит-шаблон левого операнда слева на число двоичных цифр, указанных в правом операнде.

Get = 1 << 0, // 1
Post = 1 << 1, // 2
Put = 1 << 2,  // 4
Delete = 1 << 3, // 8
Head = 1 << 4  // 16

Это семантически эквивалентно lOperand * Math.Pow(2, rOperand)

Ответ 6

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

Ответ 7

Это смещение бит. Его в основном просто перемещают биты влево, добавляя 0 к правой стороне.

public enum HttpVerbs {
    Get = 1 << 0,    // 00000001 -> 00000001 = 1
    Post = 1 << 1,   // 00000001 -> 00000010 = 2
    Put = 1 << 2,    // 00000001 -> 00000100 = 4
    Delete = 1 << 3, // 00000001 -> 00001000 = 8
    Head = 1 << 4    // 00000001 -> 00010000 = 16
}

Дополнительная информация на http://www.blackwasp.co.uk/CSharpShiftOperators.aspx

Ответ 8

В дополнение к ответу Selman22, некоторые примеры:

Я перечислю некоторые значения для list.Count и что будет цикл:

list.Count == 0: for (int i = 0; i < 1; i++)
list.Count == 1: for (int i = 0; i < 2; i++)
list.Count == 2: for (int i = 0; i < 4; i++)
list.Count == 3: for (int i = 0; i < 8; i++)

И так далее.

Ответ 9

"Бит сдвигается влево". 1 << 0 означает "принять целочисленное значение 1 и сдвинуть его биты, оставленные нулевыми битами". I.e., 00000001 остается неизменным. 1 << 1 означает "принять целочисленное значение 1 и сдвинуть его биты, оставленные на одно место". 00000001 становится 00000010.

Ответ 10

Его (<) побитовый оператор сдвига влево, он перемещает битовые значения двоичного объекта. Левый операнд задает смещаемое значение, а правый операнд определяет количество позиций, которые должны смещаться биты в значении.

В вашем случае, если значение list.count равно 4, цикл будет выполняться до тех пор, пока я < (1 < 4) который 16 (00010000)

00000001 < 4 = 00010000 (16)

Ответ 11

В выражении (1 << N) используется Shift Shift в С#.

В этом случае он используется для выполнения быстрого целочисленного вычисления 2 ^ N, где n равно от 0 до 30.

Хорошим инструментом для разработчиков young wippersnappers, которые не понимают, как работают сдвиги бит, является Windows Calc в режиме программиста, который визуализирует эффект сдвигов на подписанных числах разных размеров. Функции Lsh и Rsh равны соответственно << и >>.

Оценка с использованием Math.Pow внутри условия цикла (в моей системе) примерно в 7 раз медленнее, чем код вопроса для N = 10, зависит ли это от контекста.

Кэширование "количества циклов" в отдельной переменной немного ускорило бы его, так как выражение, включающее длину списка, не нужно было бы переоценивать на каждой итерации.

Ответ 12

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

Для каждой позиции, в которую вы смещаете двоичный номер слева, вы удваиваете исходное значение числа.

Например,

Десятичное число 5 двоичных значений, сдвинутое влево на одно, равно десятичному десяти, или десятичному удвоению 5.

Десятичное число 5 двоичное, сдвинутое слева на 3, равно десятичному значению 40, или десятичному значению 5 удваивается 3 раза.

Ответ 13

Предыдущие ответы объяснили, что он делает, но никто, кажется, не догадался, почему. Мне кажется, что причиной этого кода является то, что цикл выполняет итерацию по каждой возможной комбинации членов списка - это единственная причина, по которой я могу понять, почему вы хотите итерации до 2 ^ {списка. граф}. Следовательно, переменная i была бы плохо названа: вместо индекса (который я обычно интерпретирую как "i" в качестве значения), его биты представляют собой комбинацию элементов из списка, поэтому (например) первый элемент может быть выбрано, если бит 0 i установлен ((i & (1 << 0)) != 0), второй элемент, если бит бит установлен ((i & (1 << 1)) != 0) и так далее. 1 << list.Count - это первое целое число, которое не соответствует действительной комбинации элементов из списка, поскольку это указывает на выбор несуществующего list[list.Count].

Ответ 14

Я знаю, что этот ответ в значительной степени решен, но я думал, что визуализация может помочь кому-то.

[Fact] public void Bit_shift_left()
{
    Assert.Equal(Convert.ToInt32("0001", 2), 1 << 0); // 1
    Assert.Equal(Convert.ToInt32("0010", 2), 1 << 1); // 2
    Assert.Equal(Convert.ToInt32("0100", 2), 1 << 2); // 4
    Assert.Equal(Convert.ToInt32("1000", 2), 1 << 3); // 8
}