Что такое побитовые операторы? - PullRequest
124 голосов
/ 10 ноября 2008

Я тот, кто пишет код просто для удовольствия и в действительности не углубляется в него ни в академической, ни в профессиональной обстановке, поэтому такие вещи, как эти побитовые операторы, действительно ускользают от меня.

Я читал статью о JavaScript, который, очевидно, поддерживает побитовые операции. Я продолжаю видеть эту операцию упомянутой в некоторых местах, и я попытался прочитать, чтобы выяснить, что именно, но я просто, кажется, не понимаю ее вообще. Так что они? Четкие примеры были бы великолепны! : D

Еще несколько вопросов - каковы практические применения побитовых операций? Когда вы можете их использовать?

Ответы [ 9 ]

181 голосов
/ 10 ноября 2008

Поскольку никто не затронул тему, почему они полезны:

Я часто использую побитовые операции при работе с флагами. Например, если вы хотите передать серию флагов операции (скажем, File.Open(), когда включены режим чтения и режим записи), вы можете передать их как одно значение. Это достигается назначением каждому возможному флагу своего собственного бита в наборе битов (байтов, коротких, целых или длинных). Например:

 Read: 00000001
Write: 00000010

Таким образом, если вы хотите передать чтение и запись, вы должны передать (READ | WRITE), который затем объединит их в

00000011

Который затем может быть расшифрован на другом конце, как:

if ((flag & Read) != 0) { //...

который проверяет

00000011 &
00000001

, который возвращает

00000001

, который не равен 0, поэтому флаг указывает READ.

Вы можете использовать XOR для переключения различных битов. Я использовал это при использовании флага для указания направленных входов (вверх, вниз, влево, вправо). Например, если спрайт движется горизонтально, и я хочу, чтобы он вращался:

     Up: 00000001
   Down: 00000010
   Left: 00000100
  Right: 00001000
Current: 00000100

Я просто XOR текущее значение с помощью (ВЛЕВО | ВПРАВО), который в этом случае выключит ВЛЕВО и ВПРАВО.

Сдвиг битов полезен в нескольких случаях.

x << y

совпадает с

x * 2 y

если вам нужно быстро умножить на степень два, но не упустить 1 бит в верхнем бите - это делает число отрицательным, если оно не подписано. Это также полезно при работе с данными разных размеров. Например, чтение целого числа из четырех байтов:

int val = (A << 24) | (B << 16) | (C << 8) | D;

Предполагая, что A является старшим байтом, а D - младшим. Это закончилось бы как:

A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011

Цвета часто сохраняются таким образом (самый старший байт либо игнорируется, либо используется как альфа):

A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000

Чтобы снова найти значения, просто сдвиньте биты вправо, пока они не окажутся внизу, а затем замаскируйте оставшиеся биты высшего порядка:

Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF

0xFF совпадает с 11111111. По сути, для Red вы должны сделать следующее:

Color >> 16 = (filled in 00000000 00000000)11111111 00010101  (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)
27 голосов
/ 10 ноября 2008

Стоит отметить, что однобитовые таблицы истинности, перечисленные в качестве других ответов, работают только с одним или двумя входными битами одновременно. Что происходит, когда вы используете целые числа, такие как:

int x = 5 & 6;

Ответ заключается в двоичном расширении каждого входа:

  5 = 0 0 0 0 0 1 0 1
& 6 = 0 0 0 0 0 1 1 0
---------------------
      0 0 0 0 0 1 0 0

Каждая пара битов в каждом столбце проходит через функцию «И», чтобы получить соответствующий выходной бит в нижней строке. Таким образом, ответ на вышеприведенное выражение - 4. Процессор (в этом примере) выполнил 8 отдельных операций «И» параллельно, по одной для каждого столбца.

Я упоминаю об этом, потому что я до сих пор помню, как это "АГА!" момент, когда я узнал об этом много лет назад.

27 голосов
/ 10 ноября 2008

Битовые операторы - это операторы, работающие с битом одновременно.

И равно 1, только если оба его входа равны 1.

ИЛИ равно 1, если один или несколько его входов равны 1.

XOR равно 1, только если один из его входов равен 1.

НЕ равен 1, только если его ввод равен 0.

Их лучше всего описать как таблицы истинности. Возможности входов находятся сверху и слева, результирующий бит является одним из четырех (два в случае НЕ, поскольку он имеет только один вход) значений, показанных на пересечении двух входов.

AND|0 1      OR|0 1
---+----    ---+----
  0|0 0       0|0 1
  1|0 1       1|1 1

XOR|0 1     NOT|0 1
---+----    ---+---
  0|0 1        |1 0
  1|1 0

Один из примеров: если вам нужны только младшие 4 бита целого числа, вы И это с 15 (двоичный код 1111) так:

    203: 1100 1011
AND  15: 0000 1111
------------------
 IS  11: 0000 1011
15 голосов
/ 10 ноября 2008

Это побитовые операторы, все они поддерживаются в JavaScript:

  • op1 & op2 - Оператор AND сравнивает два бита и генерирует результат 1, если оба бита равны 1; в противном случае возвращается 0.

  • op1 | op2 - Оператор OR сравнивает два бита и генерирует результат 1, если биты дополняют друг друга; в противном случае возвращается 0.

  • op1 ^ op2 - Оператор EXCLUSIVE-OR сравнивает два бита и возвращает 1, если один из битов равен 1, и дает 0, если оба бита равны 0 или 1.

  • ~op1 - Оператор COMPLEMENT используется для инвертирования всех битов операнда.

  • op1 << op2 - Оператор SHIFT LEFT перемещает биты влево, отбрасывает крайний левый бит и назначает крайнему правому биту значение 0. Каждое перемещение влево эффективно умножает op1 на 2.

  • op1 >> op2 - Оператор SHIFT RIGHT перемещает биты вправо, отбрасывает крайний правый бит и назначает крайнему левому биту значение 0. Каждое перемещение вправо эффективно делит op1 пополам. Самый левый бит знака сохраняется.

  • op1 >>> op2 - Оператор SHIFT RIGHT - ZERO FILL перемещает биты вправо, отбрасывает крайний правый бит и присваивает крайнему левому биту значение 0. Каждое перемещение вправо эффективно делит оп1 пополам. Самый левый бит знака сбрасывается.

4 голосов
/ 10 ноября 2008

Когда упоминается термин «побитовый», иногда уточняется, что это не «логический» оператор.

Например, в JavaScript, побитовые операторы обрабатывают свои операнды как последовательность из 32 бит (нулей и единиц) ; Между тем, логические операторы обычно используются с логическими (логическими) значениями , но могут работать с не-логическими типами.

Возьмем, например, expr1 && expr2.

Возвращает expr1, если его можно конвертировать ложно; в противном случае возвращает expr2. Таким образом, при использовании с логическими значениями, && возвращает истину, если оба операнда правда; в противном случае возвращает false.

a = "Cat" && "Dog"     // t && t returns Dog
a = 2 && 4     // t && t returns 4

Как уже отмечали другие, 2 & 4 - это побитовое И, поэтому оно вернет 0.

Вы можете скопировать следующее в test.html или что-то еще и проверить:

<html>
<body>
<script>
    alert("\"Cat\" && \"Dog\" = " + ("Cat" && "Dog") + "\n"
        + "2 && 4 = " + (2 && 4) + "\n"
        + "2 & 4 = " + (2 & 4));
</script>
4 голосов
/ 10 ноября 2008

Чтобы разбить его еще немного, он имеет непосредственное отношение к двоичному представлению рассматриваемого значения.

For example (in decimal):
x = 8
y = 1

would come out to (in binary):
x = 1000
y = 0001

From there, you can do computational operations such as 'and' or 'or'; in this case:
x | y = 
1000 
0001 |
------
1001

or...9 in decimal

Надеюсь, это поможет.

2 голосов
/ 21 апреля 2016

В цифровом компьютерном программировании побитовая операция работает с одной или несколькими битовыми комбинациями или двоичными числами на уровне их отдельных битов. Это быстрое примитивное действие, поддерживаемое непосредственно процессором, и используется для манипулирования значениями для сравнения и расчетов.

операция

  • поразрядно И

  • поразрядно ИЛИ

  • поразрядно НЕ

  • поразрядно XOR

  • и т.д.

Элемент списка

    AND|0 1        OR|0 1 
    ---+----      ---+---- 
      0|0 0         0|0 1 
      1|0 1         1|1 1 

   XOR|0 1        NOT|0 1 
   ---+----       ---+--- 
     0|0 1           |1 0 
     1|1 0

Например.

    203: 1100 1011
AND  15: 0000 1111
------------------
  =  11: 0000 1011

Использование побитового оператора

  • Операторы левого и правого сдвига эквивалентны умножению и делению на x * 2 y соответственно.

Например.

int main()
{
     int x = 19;
     printf ("x << 1 = %d\n" , x <<1);
     printf ("x >> 1 = %d\n", x >>1);
     return 0;
}
// Output: 38 9
  • Оператор & может использоваться для быстрой проверки, является ли число нечетным или четным

Eg.

int main()
{
    int x = 19;
    (x & 1)? printf("Odd"): printf("Even");
    return 0;
 }
// Output: Odd
  • Быстрый поиск минимума x и y без if else statment

Например.

int min(int x, int y)
{
    return y ^ ((x ^ y) & - (x < y))
}
  • Десятичный в двоичный преобразование

Например.

#include <stdio.h>
int main ()
{
    int n , c , k ;
    printf("Enter an integer in decimal number system\n " ) ;
    scanf( "%d" , & n );
    printf("%d in binary number
    system is: \n " , n ) ;
    for ( c = 31; c >= 0 ; c -- )
    {
         k = n >> c ;
         if ( k & 1 )
              printf("1" ) ;
         else
              printf("0" ) ;
      }
      printf(" \n " );
      return 0 ;
}
  • Шифрование на шлюзе XOR является популярной техникой, потому что оно совместимо и используется программистом.
    • побитовый оператор XOR является наиболее полезным оператором с точки зрения технического интервью.

битовое смещение работает только с + ве число

Также существует широкий спектр использования побитовой логики

1 голос
/ 20 июня 2014

Это могло бы помочь думать об этом таким образом. Вот как работает AND (&):

Это в основном говорит, что оба эти числа одно, поэтому, если у вас есть два числа 5 и 3, они будут преобразованы в двоичные, и компьютер будет думать

         5: 00000101
         3: 00000011

оба равны: 00000001 0 ложно, 1 верно

Таким образом, И 5 и 3 - это одно. Оператор OR (|) делает то же самое, за исключением того, что для вывода 1 должно быть только одно из чисел, а не оба.

0 голосов
/ 10 февраля 2009

Я постоянно слышал о том, насколько медленными были битовые операторы JavaScript. Я провел несколько тестов для моего последнего сообщения в блоге и обнаружил, что они были на 40-80% быстрее, чем арифметическая альтернатива в нескольких тестах. Возможно, они были медленными. В современных браузерах я их люблю.

У меня есть один случай в моем коде, который будет быстрее и легче читать из-за этого. Я буду держать глаза открытыми для большего.

...