43

基本的にタイトルの質問。私はMVC2のソースコードを見ています:

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

そして、私はダブルレフトアングルブラッカーが何をするのか興味<<があります。

4

15 に答える 15

130

あなたが書くとき

1 << n

000000001ビットの組み合わせをn左にシフトし、n2 の指数に入れます。

2^n

そう

1 << 10

本当にそうです

1024

たとえば 5 つの項目のリストの場合、for32 回循環します。

于 2014-01-29T10:42:25.943 に答える
82

オペレーターといいleft-shiftます。ドキュメントを見てみましょう

左シフト演算子は、第 1 オペランドのビット パターンを、第 2 オペランドで指定されたビット数だけ左にシフトします。シフト操作によって空になったビットはゼロで埋められます。これは、シフトして回転する操作ではなく、論理シフトです。

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

1 ビット左に移動することは、2 倍することと同じです。実際、ビットを移動することは、標準の乗算よりも高速です。この事実を示す例を見てみましょう。

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
于 2014-01-29T10:41:36.360 に答える
63

それはビットごとの左シフト演算子になります。

左にシフトするたびに、値は事実上 2 倍になります。したがって、たとえば、書き込みvalue << 3は値を 8 倍します。

内部で実際に行うことは、値の実際のビットをすべて 1 つの場所に移動することです。したがって、値が 12 (10 進数) の場合、2 進数では00001100; 左に 1 桁ずらすと00011000、または 24 になります。

于 2010-03-22T15:33:42.467 に答える
36

それが左ビットシフト演算子です。左オペランドのビット パターンを、右オペランドで指定された 2 進数の数だけ左にシフトします。

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)

于 2010-03-22T15:33:30.590 に答える
23

ループの目的は、リスト内の項目セットのすべてのサブセットを生成または操作することです。また、ループ本体には、かなりのビット (har har) ビット演算、つまり別の左シフトとビット演算 and の両方が含まれている可能性が最も高いです。(したがって、Pow を使用するように書き直すのは非常にばかげているでしょう。実際にそれを提案した人がこれほど多くいたとは信じられません。)

于 2014-01-29T13:48:47.390 に答える
15

それは少しシフトしています。基本的には、右側に 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 をご覧ください。

于 2010-03-22T15:34:13.977 に答える
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++)

などなど。

于 2014-01-29T10:44:23.983 に答える
9

「左にビットシフト」 1 << 0「整数値1を取り、そのビットをゼロビット左にシフトする」ことを意味します。つまり、00000001変わらないままです。 1 << 1「整数値 1 を取り、そのビットを 1 桁左にシフトする」ことを意味します。 00000001になり00000010ます。

于 2010-03-22T15:35:31.760 に答える
8

その (<<) ビット単位の左シフト演算子で、バイナリ オブジェクトのビット値を移動します。左のオペランドはシフトする値を指定し、右のオペランドは値のビットをシフトする位置の数を指定します。

あなたの場合、list.count の値が 4 の場合、ループは i < (1<< 4)、つまり16 (00010000)まで実行されます。

00000001 << 4 = 00010000(16)

于 2014-01-29T12:54:14.193 に答える
7

それは多くの回答で暗示されていますが、直接述べられることはありません...

2 進数を左にシフトする位置ごとに、数値の元の値が 2 倍になります。

例えば、

左に 1 シフトされた 10 進数 5 バイナリは 10 進数 10、または 10 進数 5 を 2 倍したものです。

3 だけ左にシフトされた 10 進数 5 バイナリは 10 進数 40、または 10 進数 5 を 3 回倍増したものです。

于 2014-01-29T20:19:41.810 に答える
7

(1 << N)は、C# でビット シフトを使用します。

この場合、2^N の高速整数評価を実行するために使用されています。ここで、n は 0 から 30 です。

ための良いツール若いホイッパースナッパービット シフトがどのように機能するかを理解していない開発者は、さまざまなサイズの符号付き数値に対するシフトの効果を視覚化するプログラマ モードの Windows Calc です。Lshおよび関数は、それぞれ および とRsh同等です。<<>>

ループ条件内で Math.Pow を使用して評価すると、(私のシステムでは) N = 10 の質問コードよりも約 7 倍遅くなります。これが問題になるかどうかは、コンテキストによって異なります。

「ループカウント」を別の変数にキャッシュすると、リストの長さを含む式を反復ごとに再評価する必要がないため、わずかに速度が向上します。

于 2014-01-29T18:29:11.833 に答える
6

以前の回答でそれが何をするのか説明されていますが、その理由について誰も推測していないようです。このコードの理由は、リストのメンバーの可能な組み合わせごとにループが繰り返されているためである可能性が非常に高いと思われます。これが、2^{list.カウント}。したがって、変数のi名前は不適切です: インデックス (私が通常 'i' を意味すると解釈するもの) の代わりに、そのビットはリストの項目の組み合わせを表すため、(たとえば) ビットの場合、最初の項目が選択される可能性があります。ゼロiが設定されている場合 ( (i & (1 << 0)) != 0)、ビット 1 が設定されている場合は 2 番目の項目 ( (i & (1 << 1)) != 0) などです。1 << list.Countしたがって、存在しない が選択されていることを示すため、 はリストの項目の有効な組み合わせに対応しない最初の整数ですlist[list.Count]

于 2014-01-29T18:53:22.590 に答える
5

私はこの答えがほとんど解決されていることを知っていますが、視覚化が誰かを助けるかもしれないと思いました.

[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
}
于 2010-03-22T15:44:16.833 に答える
0

<<左ビットシフト演算子です。2 進数で 00000011 の 3 がある場合、3 << 200001100、または 10 進数で 12 と書くことができます。

于 2020-11-02T11:00:13.010 に答える