简体   繁体   English

C#中的两个左尖括号“<<”是什么意思?

[英]What do two left-angle brackets “<<” mean in C#?

Basically the questions in the title.基本上是标题中的问题。 I'm looking at the MVC 2 source code:我正在查看 MVC 2 源代码:

[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 << 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:您将位组合000000001左移n次,从而将n放入 2 的指数中:

2^n

So所以

1 << 10

Really is真的是

1024

For a list of say 5 items your for will cycle 32 times.对于 5 个项目的列表,您的for将循环 32 次。

It is called left-shift operator.它被称为left-shift运算符。 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:演示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

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.对于每个左移,该值有效地乘以 2。因此,例如,写入value << 3会将值乘以 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 ;因此,如果您的值为 12(十进制),则二进制为00001100 shifting it left one place will turn that into 00011000 , or 24.将它左移一位将把它变成00011000或 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. 14 的二进制等效值是00001110将其移位 2 次意味着从右侧推零并将每个数字移到左侧,使其00111000等于 56。

视觉的

In your example:在你的例子中:

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

and so on.等等。 In general it is equal 2 ^ list.Count (2 raised to the power of list.Count)通常它等于2 ^ list.Count (2 的 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)这在语义上等同于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.并且循环体很可能还有一个很好的位 (har har) 按位运算,即另一个左移和按位与。 (So rewriting it to use Pow would be mighty stupid, I can hardly believe there were so many people that actually suggested that.) (所以用 Pow 重写它是非常愚蠢的,我简直不敢相信有这么多人真的建议这样做。)

Thats bit shifting.那是位移。 Its basically just moving the bits to the left by adding 0's to the right side.它基本上只是通过在右侧添加 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
}

More info at http://www.blackwasp.co.uk/CSharpShiftOperators.aspx更多信息请访问http://www.blackwasp.co.uk/CSharpShiftOperators.aspx

In addition to Selman22's answer, some examples:除了 Selman22 的回答,还有一些例子:

I'll list some values for list.Count and what the loop would be:我将列出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++)

And so forth.等等。

"Bit shift left." “左移。” 1 << 0 means "take the integer value 1 and shift its bits left by zero bits." 1 << 0表示“取整数值 1 并将其位左移零位。” Ie, 00000001 stays unchanged.即, 00000001保持不变。 1 << 1 means "take the integer value 1 and shift its bits left one place." 1 << 1表示“取整数值 1 并将其位左移一位。” 00000001 becomes 00000010 . 00000001变成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)在您的情况下,如果 list.count 的值为 4,则循环将运行直到 i < (1<< 4) 即16 (00010000)

00000001 << 4 = 00010000(16) 00000001 << 4 = 00010000(16)

The expression (1 << N) uses a Bit Shift in c#.表达式(1 << N)在 c# 中使用位移位

In this case it's being used to perform a fast integer evalution of 2^N, where n is 0 to 30.在这种情况下,它用于执行 2^N 的快速整数计算,其中 n 是 0 到 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.不了解位移如何工作的开发人员是程序员模式下的 Windows Calc,它可视化了位移对各种大小的有符号数的影响。 The Lsh and Rsh functions equate to << and >> respectively. LshRsh函数分别等于<<>>

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.在循环条件内使用 Math.Pow 进行评估(在我的系统上)比 N = 10 的问题代码慢约 7 倍,这是否重要取决于上下文。

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.在单独的变量中缓存“循环计数”会稍微加快速度,因为不需要在每次迭代时重新评估涉及列表长度的表达式。

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.十进制 5 二进制左移 1 是十进制 10,或十进制 5 加倍。

Decimal 5 binary shifted left by 3 is decimal 40, or decimal 5 doubled 3 times.十进制 5 二进制左移 3 是十进制 40,或十进制 5 翻倍 3 次。

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}.在我看来,这段代码的原因很可能是循环正在迭代列表成员的每个可能组合——这是我能理解为什么你想要迭代到 2^{list.list 的唯一原因。数数}。 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.因此,变量i将被错误命名:而不是索引(这是我通常将 'i' 解释为含义的意思),它的位表示列表中项目的组合,因此(例如)可以选择第一个项目,如果位的零i被设置( (i & (1 << 0)) != 0 )时,第二项如果一个位被设置( (i & (1 << 1)) != 0 )等等。 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] .因此, 1 << list.Count是第一个与列表中项目的有效组合不对应的整数,因为它表示选择了不存在的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.如果您有数字 3,即二进制的 00000011,您可以写3 << 2 ,即 00001100,或十进制的 12。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM