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



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Все эти побитовые операторы поддерживаются в 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 пополам. Самый левый бит знака отбрасывается.
"если биты дополняют друг друга" - что?
@AndreyTyukin два бита являются дополнительными, если один из них равен 1, а другой - 0.
@JeffHillman Согласно вашему описанию в комментарии, 1 и 1 не являются «дополнительными». Тогда мне непонятно, почему 1 | 1 дает 1, а не 0, и чем | должен отличаться от ^. Несколько дней назад мне пришлось использовать этот вопрос / ответ в качестве дублирующей цели, и мне хотелось, чтобы через 10 лет у кого-то был более четкий канонический дубликат для такого рода вопросов.
Побитовые операторы - это операторы, которые работают понемногу.
И равно 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 отдельных операций «И» параллельно, по одной для каждого столбца.
Я упоминаю об этом, потому что до сих пор помню это «АГА!». момент, когда я узнал об этом много лет назад.
Вау, теперь это имеет гораздо больше смысла. Это звучало намного сложнее, чем кажется. Спасибо. Я не уверен, какой ответ выбрать в качестве правильного, так как есть множество хороших ответов, и я не могу проголосовать за него, поэтому ... спасибо
Чтобы разбить его немного больше, он имеет много общего с двоичным представлением рассматриваемого значения.
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
Надеюсь это поможет.
| - это ИЛИ операции?
По какой-то причине это имело для меня наибольший смысл. Все еще не уверен насчет части x | y = 1000 0001 |, хотя
Когда упоминается термин «поразрядный», иногда уточняется, что это не «логический» оператор.
Например, в 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 ^?
Я все время слышал о том, насколько медленными были побитовые операторы 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
Использование побитового оператора
Например.
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
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 ;
}
побитовое смещение работает только с положительным числом
Также существует широкий спектр использования побитовой логики.
"сложность и редкость ..."?
The left-shift and right-shift operators are equivalent to multiplication and division by x * 2y respectively. Верно! muyiy.cn/question/program/102.htmlмое решение repl.it/@xgqfrms/…
Если у вас возникнут дополнительные вопросы, вы можете добавить новый вопрос SO и сослаться на него. Так вы, вероятно, получите лучший набор ответов.