开发者

What do two left-angle brackets "<<" mean in C#?

Basically the questions in the title. I'm looking at the MVC 2 source code:

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

and I'm just curious as to what the double left angle brackers 开发者_StackOverflow社区<< does.


When you write

1 << n

You shift the bit combination 000000001 for n times left and thus put n into the exponent of 2:

2^n

So

1 << 10

Really is

1024

For a list of say 5 items your for will cycle 32 times.


It is called left-shift operator. Take a look at the documentation

The left-shift operator causes the bit pattern in the first operand to be shifted to the left by the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled. This is a logical shift instead of a shift-and-rotate operation.

Simple example that demonstrates the left-shift operator:

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

Moving one bit to left is equivelant to multiple by two.In fact,moving bits are faster than standart multiplication.Let's take a look at an example that demonstrates this fact:

Let's say we have two methods:

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);
            }
      }
}

And we want to test them like this:

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

Here is the results:

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


That would be the bitwise left shift operator.

For each shift left, the value is effectively multiplied by 2. So, for example, writing value << 3 will multiply the value by 8.

What it really does internally is move all of the actual bits of the value left one place. So if you have the value 12 (decimal), in binary that is 00001100; shifting it left one place will turn that into 00011000, or 24.


It is Bitwise shift left it works by shifting digits of binary equivalent of number by the given (right hand side) numbers.

so:

temp = 14 << 2

binary equivalent of 14 is 00001110 shifting it 2 times means pushing zero from right hand side and shifting each digit to left side which make it 00111000 equals to 56.

What do two left-angle brackets "<<" mean in C#?

In your example:

i < (1 << list.Count)
  • 0000000001 = 1 if list.Count = 0 result is 0000000001 = 1
  • 0000000001 = 1 if list.Count = 1 result is 0000000010 = 2
  • 0000000001 = 1 if list.Count = 2 result is 0000000100 = 4
  • 0000000001 = 1 if list.Count = 3 result is 0000001000 = 8

and so on. In general it is equal 2 ^ list.Count (2 raised to the power of list.Count)


That's the left bitshift operator. It shifts the bit pattern of the left operand to the left by the number of binary digits specified in the right operand.

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

This is semantically equivalent to lOperand * Math.Pow(2, rOperand)


The purpose of the loop is most likely to generate or operate on all subsets of the set of items in the list. And the loop body most likely also has a good bit (har har) of bitwise operations, namely both another left-shift and bitwise-and. (So rewriting it to use Pow would be mighty stupid, I can hardly believe there were so many people that actually suggested that.)


Thats bit shifting. Its basically just moving the bits to the left by adding 0's to the right side.

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
}

More info at http://www.blackwasp.co.uk/CSharpShiftOperators.aspx


In addition to Selman22's answer, some examples:

I'll list some values for list.Count and what the loop would be:

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++)

And so forth.


"Bit shift left." 1 << 0 means "take the integer value 1 and shift its bits left by zero bits." I.e., 00000001 stays unchanged. 1 << 1 means "take the integer value 1 and shift its bits left one place." 00000001 becomes 00000010.


Its (<<) a bitwise left shift operator, it moves the bit values of a binary object. The left operand specifies the value to be shifted and the right operand specifies the number of positions that the bits in the value are to be shifted.

In your case if the value of list.count is 4 then loop will run till i < (1<< 4) which is 16 (00010000)

00000001 << 4 = 00010000(16)


It is implied in a number of answers but never stated directly...

For every position that you shift a binary number left, you double the original value of the number.

For example,

Decimal 5 binary shifted left by one is decimal 10, or decimal 5 doubled.

Decimal 5 binary shifted left by 3 is decimal 40, or decimal 5 doubled 3 times.


The expression (1 << N) uses a Bit Shift in c#.

In this case it's being used to perform a fast integer evalution of 2^N, where n is 0 to 30.

A good tool for young whippersnappers developers that don't understand how bit shifts work is Windows Calc in programmer mode, which visualises the effect of shifts on signed numbers of various sizes. The Lsh and Rsh functions equate to << and >> respectively.

Evaluating using Math.Pow inside the loop condition is (on my system) about 7 times slower than the question code for N = 10, whether this matters depends on the context.

Caching the "loop count" in a separate variable would speed it up slightly as the expression involving the list length would not need to be re-evaluated on every iteration.


Previous answers have explained what it does, but nobody seems to have taken a guess as to why. It seems quite likely to me that the reason for this code is that the loop is iterating over each possible combination of members of a list -- this is the only reason I can see why you would want to iterate up to 2^{list.Count}. The variable i would therefore be badly named: instead of an index (which is what I usually interpret 'i' as meaning), its bits represent a combination of items from the list, so (for example) the first item may be selected if bit zero of i is set ((i & (1 << 0)) != 0), the second item if bit one is set ((i & (1 << 1)) != 0) and so on. 1 << list.Count is therefore the first integer that does not correspond to a valid combination of items from the list, as it would indicate selection of the non-existant list[list.Count].


I know this answer is pretty much solved, but I thought the visualization might help someone.

[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
}


<< is the left bit shift operator. If you have the number 3, which is 00000011 in binary, you can write 3 << 2, which is 00001100, or 12 in decimal.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜