.net-在C#中,两个左尖括号“ <<”是什么意思?

基本上是标题中的问题。 我正在看MVC 2源代码:

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

而我只是对双左角2979182585387156156480的功能感到好奇。

14个解决方案
131 votes

当你写

1 << n

您将位组合for左移n次,然后将n放入2的指数中:

2^n

所以

1 << 10

真的是

1024

对于说5项的清单,您的for将循环32次。

pid answered 2020-07-23T13:28:04Z
82 votes

它称为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

向左移一位等于乘以2.实际上,向左移位比标准的乘法快。让我们来看一个演示这一事实的示例:

假设我们有两种方法:

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
Selman22 answered 2020-07-23T13:28:51Z
61 votes

那将是按位左移运算符。

对于每个左移,该值将有效地乘以2。因此,例如,写入00001100将值乘以8。

它真正在内部执行的操作是将值的所有实际位都移到一位。 因此,如果您具有二进制值00001100,则值为12(十进制); 将其左移一位将变成00011000或24。

Aaronaught answered 2020-07-23T13:27:27Z
57 votes

这是按位左移,它通过将给定的(右手边的)数字移动与数字二进制等效的数字来工作。

所以:

temp = 14 << 2

14的二进制等效值是2 ^ list.Count将其移位2次表示从右手侧推零并将每个数字移至左侧,这使其00111000等于56。

visual

在您的示例中:

i < (1 << list.Count)
  • 如果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则为0000000001 = 1

等等。 通常等于2 ^ list.Count(2升为list.Count的幂)

Zaheer Ahmed answered 2020-07-23T13:29:46Z
36 votes

那是左移位运算符。 它将左操作数的位模式向左移动右操作数中指定的二进制数。

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)

Adam Robinson answered 2020-07-23T13:30:13Z
23 votes

循环的目的最有可能在列表中的项目集中的所有子集上生成或操作。 循环体很可能还具有良好的按位运算(har har),即另一个左移和按位与。 (因此,将其重写为使用Pow会非常愚蠢,我简直不敢相信会有这么多人真正提出这一建议。)

user2451227 answered 2020-07-23T13:30:33Z
15 votes

多数民众赞成在转移。 它基本上只是通过在右侧增加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]

Fabian answered 2020-07-23T13:30:57Z
12 votes

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

依此类推。

Thorsten Dittmar answered 2020-07-23T13:31:26Z
9 votes

“左移。” 1 << 0的意思是“取整数值1并将其位左移零位”。 即00000001保持不变。 1 << 1的意思是“取整数值1并将其位左移一位。” 00000001变为00000010

Dathan answered 2020-07-23T13:31:48Z
8 votes

它的(<<)按位左移运算符,它移动二进制对象的位值。 左操作数指定要移位的值,而右操作数指定值中要移位的位的数目。

在您的情况下,如果list.count的值为4,则循环将运行直到i <(1 << 4)这是16(00010000)

00000001 << 4 = 00010000(16)

gaurav answered 2020-07-23T13:32:17Z
7 votes

许多答案中都暗含了它,但从未直接指出。

对于将二进制数向左移动的每个位置,都将数字的原始值加倍。

例如,

左移十进制的十进制5二进制是十进制10,或十进制5加倍。

左移3的十进制5二进制是十进制40,或十进制5加倍3次。

GaTechThomas answered 2020-07-23T13:32:54Z
7 votes

表达式(1 << N)在c#中使用位移位。

在这种情况下,它用于执行2 ^ N的快速整数评估,其中n为0到30。

一个很好的工具年轻的鲷鱼不了解位移位如何工作的开发人员是程序员模式下的Windows Calc,它可以可视化移位对各种大小的带符号数字的影响。LshRsh功能分别相当于<<>>

对于N = 10,在循环条件内使用Math.Pow进行评估(在我的系统上)比问题代码慢7倍左右,这是否取决于上下文。

在单独的变量中缓存“循环计数”会稍微加快速度,因为涉及列表长度的表达式不需要在每次迭代时都重新计算。

Peter Wishart answered 2020-07-23T13:33:41Z
6 votes

先前的答案已经解释了它的作用,但是似乎没有人猜测其原因。 在我看来,这段代码的原因很可能是循环正在遍历列表成员的每种可能组合,这是我看到为什么要迭代最多2 ^ {list的唯一原因。 计数}。 因此,变量i将被错误命名:代替索引(我通常将其解释为“ i”的含义),其位表示列表中各项的组合,因此(例如)如果 设置i的位0((i & (1 << 0)) != 0),如果设置了位1((i & (1 << 1)) != 0),则第二项,依此类推。 因此,1 << list.Count是第一个整数,它不对应于列表中的有效项组合,因为它将指示选择了不存在的list[list.Count]

Jules answered 2020-07-23T13:34:02Z
5 votes

我知道这个答案已经解决了很多,但我认为可视化可能会对某人有所帮助。

[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
}
Mark answered 2020-07-23T13:34:23Z
translate from https://stackoverflow.com:/questions/2493517/what-do-two-left-angle-brackets-mean-in-c