Что такое побитовые операторы?

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

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

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

Если у вас возникнут дополнительные вопросы, вы можете добавить новый вопрос SO и сослаться на него. Так вы, вероятно, получите лучший набор ответов.

Greg Hewgill 10.11.2008 03:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
133
1
21 885
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Все эти побитовые операторы поддерживаются в 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. Каждое движение вправо эффективно делит op1 пополам. Самый левый бит знака отбрасывается.

"если биты дополняют друг друга" - что?

Andrey Tyukin 24.05.2019 16:38

@AndreyTyukin два бита являются дополнительными, если один из них равен 1, а другой - 0.

Jeff Hillman 29.05.2019 19:05

@JeffHillman Согласно вашему описанию в комментарии, 1 и 1 не являются «дополнительными». Тогда мне непонятно, почему 1 | 1 дает 1, а не 0, и чем | должен отличаться от ^. Несколько дней назад мне пришлось использовать этот вопрос / ответ в качестве дублирующей цели, и мне хотелось, чтобы через 10 лет у кого-то был более четкий канонический дубликат для такого рода вопросов.

Andrey Tyukin 29.05.2019 19:08

Побитовые операторы - это операторы, которые работают понемногу.

И равно 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

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

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 отдельных операций «И» параллельно, по одной для каждого столбца.

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

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

click 10.11.2008 03:21

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

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

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

| - это ИЛИ операции?
Si8 03.08.2016 23:50

По какой-то причине это имело для меня наибольший смысл. Все еще не уверен насчет части x | y = 1000 0001 |, хотя

samayo 17.03.2017 13:45

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

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

Возьмем, к примеру, expr1 && expr2.

Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns 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>
Ответ принят как подходящий

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

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

 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 текущего значения с помощью (LEFT | RIGHT), который в этом случае отключает LEFT и RIGHT.

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

x << y

такой же как

x * 2y

если вам нужно быстро умножить на степень двойки, но следите за тем, чтобы 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)

x << n, значит, n должно быть в виде значения 2 ^?

Ahmed C 05.06.2020 12:26

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

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

Возможно, стоит подумать об этом так. Вот как работает AND (&):

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

         5: 00000101
         3: 00000011

оба едины: 00000001 0 - ложь, 1 - правда

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

In digital computer programming, a bitwise operation operates on one or more bit patterns or binary numerals at the level of their individual bits. It is a fast, primitive action directly supported by the processor, and is used to manipulate values for comparisons and calculations.

операции:

  • побитовое И

  • побитовое ИЛИ

  • побитовое НЕ

  • побитовое 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 * 2y соответственно.

Например.

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

Например.

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

Например.

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 - самый полезный оператор с точки зрения технического собеседования.

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

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

"сложность и редкость ..."?

Jonathan Cross 24.09.2017 16:35
The left-shift and right-shift operators are equivalent to multiplication and division by x * 2y respectively. Верно! muyiy.cn/question/program/102.html
xgqfrms 15.08.2019 04:31

мое решение repl.it/@xgqfrms/…

xgqfrms 15.08.2019 05:11

Другие вопросы по теме