Co oznaczają dwa nawiasy kątowe "<<" w C#?

W zasadzie pytania w tytule. Patrzę na kod źródłowy MVC 2:

[Flags]
public enum HttpVerbs {
    Get = 1 << 0,
    Post = 1 << 1,
    Put = 1 << 2,
    Delete = 1 << 3,
    Head = 1 << 4
}
A ja jestem ciekaw, co robią dwa lewe Kątowniki.
Author: lancscoder, 2010-03-22

14 answers

To byłby operator przesunięcia w lewo .

Dla każdego przesunięcia w lewo wartość jest skutecznie pomnożona przez 2. Tak więc, na przykład, zapis value << 3 pomnoży wartość przez 8.

To, co naprawdę robi wewnętrznie, to przesunięcie wszystkich rzeczywistych bitów wartości w jedno miejsce. Więc jeśli masz wartość 12 (dziesiętna), w binarnym, który jest 00001100; przesunięcie go w lewo o jedno miejsce zmieni to na 00011000, lub 24.

 59
Author: Aaronaught,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 15:33:42

Kiedy piszesz

1 << n

Przesuwa się kombinację bitów 000000001 dla n razy w lewo i w ten sposób dodaje n do wykładnika 2:

2^n

Więc

1 << 10

Naprawdę jest

1024

Dla listy powiedzmy 5 pozycji for będzie cykl 32 razy.

 131
Author: pid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 10:42:25

Nazywa się operatorem left-shift. Zapoznaj się z dokumentacją

Operator przesunięcia w lewo powoduje przesunięcie wzorca bitowego w pierwszym operandie w lewo o liczbę bitów określoną przez drugi operand. Bity opuszczone przez operację shift są wypełnione zerem. Jest to logiczne przesunięcie zamiast operacji przesunięcia i obrotu.

Prosty przykład pokazujący 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

Przesunięcie o jeden bit w lewo jest równoznaczne z wielokrotne przez two.In fakt, ruchome bity są szybsze niż standardowe mnożenie.Spójrzmy na przykład, który demonstruje ten fakt:

Powiedzmy, że mamy dwie metody:

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

I chcemy je przetestować w ten sposób:

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

Oto wyniki:

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
 82
Author: Selman22,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-15 02:58:33

Jest to przesunięcie w lewo działa poprzez przesunięcie cyfr binarnego odpowiednika liczby o podane (po prawej stronie) liczby.

Więc:

temp = 14 << 2

Binarnym odpowiednikiem 14 jest 00001110 przesunięcie go 2 razy oznacza przesunięcie zera z prawej strony i przesunięcie każdej cyfry na lewą stronę, co sprawia, że 00111000 jest równe 56.

visual

W twoim przykładzie:

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

I tak dalej. Ogólnie jest równa 2 ^ list.Count (2 podniesiona do potęgi listy.Count)

 57
Author: Zaheer Ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 16:12:59

Tolewy operator bitshift . Przesuwa ona wzór bitowy lewego operandu na lewo o liczbę cyfr binarnych określoną w prawym operandie.

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

Jest to semantycznie równoważne lOperand * Math.Pow(2, rOperand)

 36
Author: Adam Robinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 15:33:30

Celem pętli jest najprawdopodobniej wygenerowanie lub działanie na wszystkich podzbiorach zbioru pozycji na liście. A ciało pętli najprawdopodobniej ma również dobry bit (har har) operacji bitowych, mianowicie zarówno kolejny lewy-shift i bitwise-and. (Więc przepisanie go na Pow byłoby bardzo głupie, trudno mi uwierzyć, że było tak wielu ludzi, którzy faktycznie to zasugerowali.)

 23
Author: user2451227,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 13:48:47

To trochę się zmienia. Jego w zasadzie po prostu przesuwając bity w lewo, dodając 0 do prawej strony.

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
}

Więcej informacji na http://www.blackwasp.co.uk/CSharpShiftOperators.aspx

 15
Author: Fabian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-31 11:30:01

Oprócz odpowiedzi Selman22, kilka przykładów:

Podam kilka wartości dla list.Count i jaka byłaby pętla:

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

I tak dalej.

 12
Author: Thorsten Dittmar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 21:23:06

"Bit shift left."1 << 0 oznacza " weź wartość całkowitą 1 i przesuń jej bity w lewo o bity zerowe."Tzn. 00000001 pozostaje bez zmian. 1 << 1 oznacza " weź wartość całkowitą 1 i przesuń jej bity w lewo o jedno miejsce."00000001 staje się 00000010.

 9
Author: Dathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 15:35:31

Jego (

W Twoim przypadku jeśli wartość list.count is 4 then loop will run till I 16 (00010000)

00000001

 8
Author: gaurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 12:54:14

Jest to sugerowane w wielu odpowiedziach, ale nigdy nie podane bezpośrednio...

Dla każdej pozycji, w której przesuniesz liczbę binarną w lewo, podwoisz pierwotną wartość liczby.

Na przykład,

Decimal 5 Binary przesunięte w lewo o jeden to decimal 10, lub decimal 5 podwojone.

Decimal 5 Binary przesunięte w lewo przez 3 to decimal 40, lub decimal 5 podwojone 3 razy.

 7
Author: GaTechThomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 20:19:41

Wyrażenie (1 << N)używa przesunięcia bitowego W c#.

W tym przypadku jest on używany do szybkiej ewaluacji liczby całkowitej 2^n, gdzie n wynosi od 0 do 30.

Dobrym narzędziem dla młodych whippersnappersów programistów, którzy nie rozumieją, jak działają zmiany bitowe, jest Windows Calc w trybie programistycznym, który wizualizuje wpływ zmian na podpisane liczby o różnych rozmiarach. Funkcje Lsh i Rsh odpowiadają odpowiednio << i >>.

Ocena za pomocą matematyki.Pow wewnątrz warunku pętli jest (w moim systemie) około 7 razy wolniejszy niż kod zapytania dla N = 10, czy to ma znaczenie zależy od kontekstu.

Buforowanie "liczby pętli" w osobnej zmiennej przyspieszyłoby ją nieco, ponieważ wyrażenie zawierające długość listy nie musiałoby być ponownie oceniane przy każdej iteracji.

 7
Author: Peter Wishart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:42

Poprzednie odpowiedzi wyjaśniały co robi, ale wydaje się, że nikt nie zgadł Dlaczego . Wydaje mi się całkiem prawdopodobne, że powodem tego kodu jest to, że pętla jest iteracją nad każdą możliwą kombinacją członków listy-to jest jedyny powód, dla którego widzę, dlaczego chcesz iterację do 2^{Lista.Hrabia}. Zmienna i byłaby więc źle nazwana: zamiast indeksu (co zwykle interpretuję jako znaczenie "i"), jej bity reprezentują kombinacja elementów z listy, tak więc (na przykład) pierwszy element może być wybrany, jeśli bit zero i jest ustawiony ((i & (1 << 0)) != 0), drugi element jest ustawiony ((i & (1 << 1)) != 0) i tak dalej. 1 << list.Count jest więc pierwszą liczbą całkowitą, która nie odpowiada poprawnej kombinacji elementów z listy, ponieważ wskazywałaby wybór nieistniejącego list[list.Count].

 6
Author: Jules,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 18:53:22

Wiem, że ta odpowiedź jest rozwiązana, ale pomyślałem, że wizualizacja może komuś pomóc.

[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
}
 5
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 15:44:16