代码之家  ›  专栏  ›  技术社区  ›  lancscoder

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

  •  42
  • lancscoder  · 技术社区  · 16 年前

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

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

    我只是好奇什么是双左角支架 << 做。

    14 回复  |  直到 11 年前
        1
  •  60
  •   Aaronaught    16 年前

    那就是 bitwise left shift 操作员。

    对于左移,该值有效地乘以2。例如,写作 value << 3 将该值乘以8。

    它在内部真正做的是将值的所有实际位移到一个位置。所以如果你有12(十进制)的值,用二进制表示 00001100 把它移到一个地方就会变成 00011000 或24。

        2
  •  131
  •   pid    12 年前

    当你写作时

    1 << n
    

    你改变钻头组合 000000001 对于 n 剩下的时间 n 以2的指数表示:

    2^n
    

    所以

    1 << 10
    

    真的是

    1024
    

    对于5个项目的列表, for 循环32次。

        3
  •  82
  •   Selman22    12 年前

    它被称为 left-shift 操作员。看看 documentation

    左移位运算符使第一个操作数中的位模式按第二个操作数指定的位数向左移位。移位操作腾出的位被零填充。这是一个逻辑移位,而不是移位和旋转操作。

    演示 左移 操作员:

    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
  •  57
  •   Zaheer Ahmed    12 年前

    它是 bitwise shift-left it works by shifting digits of binary equivalent of number by the given(right hand side)numbers.

    所以:

    temp=14<<2
    < /代码> 
    
    

    二进制等效值14是00001110shifting it 2 times means pushing zero from right hand side and shifting each digit to left side which make it00111000equals to 56.

    < Buff行情>

    < /块引用>

    在您的示例中:

    i<(1<<list.count)
    
    • 000000000 1=1iflist.count=0result is000000000 1=1
    • 000000000 1=1iflist.count=1result is00000000 10=2
    • 000000000 1=1iflist.count=2result is0000000 100=4
    • 000000000 1=1iflist.count=3result is000000 1000=8

    等。一般来说,它是相等的

    它的工作原理是将数字的二进制等价物的数字按给定的(右侧)数字移动。

    所以:

    temp = 14 << 2
    

    二进制等价物14是00001110移动2次意味着从右手边将零位推到左手边,然后将每个数字移动到左手边。00111000等于56。

    visual

    在您的示例中:

    i < (1 << list.Count)
    
    • 000000000 1=1如果计数=0结果是000000000 1=1
    • 000000000 1=1如果计数=1结果是00000000 10=2
    • 000000000 1=1如果计数=2结果是0000000 100=4
    • 000000000 1=1如果计数=3结果是000000 1000=8

    等等。一般来说,它是相等的2 ^ list.Count(2提升到list.count的幂级)

        5
  •  36
  •   Adam Robinson    16 年前

    那就是 left bitshift 操作员。它按右操作数中指定的二进制位数将左操作数的位模式向左移动。

    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
  •  23
  •   user2451227    12 年前

    循环的目的很可能在列表中的一组项的所有子集上生成或操作。循环体也很可能有一个很好的位操作(har-har),即另一个左移位和位和。(所以把它改写成使用pow是非常愚蠢的,我简直不敢相信有这么多人真的这么建议。)

        7
  •  15
  •   Fabian    12 年前

    那是位移动。它基本上就是通过在右边加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
  •  12
  •   chue x    12 年前

    除了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
  •  9
  •   Dathan    16 年前

    “位左移。” 1 << 0 表示“取整数值1并将其位左移零位”,即, 00000001 保持不变。 1 << 1 表示“取整数值1并将其位左移一位。” 0000000 1 变成 00000010 .

        10
  •  8
  •   gaurav    12 年前

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

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

    00000001<<4=00010000(16)

        11
  •  7
  •   GaTechThomas    12 年前

    这在许多答案中是隐含的,但从未直接说明…

    对于左移一个二进制数的每个位置,都要使该数的原始值翻倍。

    例如,

    十进制5的二进制移位1是十进制10,或十进制5的两倍。

    十进制5的二进制移位3是十进制40,或十进制5的3倍。

        12
  •  7
  •   Community Mohan Dere    9 年前

    表达式 (1 << N) 使用A Bit Shift 在C中。

    在这种情况下,它被用来执行2^n的快速整数计算,其中n是0到30。

    一个很好的工具 年轻的打盹儿 不了解位移如何工作的开发人员是程序员模式下的WindowsCalc,它可视化了位移对不同大小的有符号数的影响。 这个 Lsh Rsh 函数等于 << >> 分别。

    在循环条件中使用math.pow进行评估(在我的系统中)比n=10的问题代码慢7倍,这是否重要取决于上下文。

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

        13
  •  6
  •   Jules    12 年前

    以前的答案已经解释过了 什么 是的,但似乎没人猜到 为什么? . 在我看来,这段代码的原因很可能是循环正在迭代一个列表中每个可能的成员组合——这是我能理解为什么要迭代最多2 ^ list.count的唯一原因。变量 i 因此命名错误:它的位代表列表中项目的组合,而不是索引(我通常将“i”解释为含义),因此(例如)如果 被设置( (i & (1 << 0)) != 0 )第二项,如果设置了位1( (i & (1 << 1)) != 0 等等。 1 << list.Count 因此,是第一个与列表中的有效项组合不对应的整数,因为它将指示选择不存在项 list[list.Count] .

        14
  •  5
  •   Mark    16 年前

    我知道这个答案已经很好地解决了,但是我认为可视化可能会帮助一些人。

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