JS JavaScript Битовые операции
Побитовые операторы JavaScript
Оператор | Имя | Описание |
---|---|---|
& | AND | Устанавливает каждый бит 1, если оба бита 1 |
| | OR | Задает каждый бит 1, если один из двух битов 1 |
^ | XOR | Задает каждый бит 1, если только один из двух битов 1 |
~ | NOT | Переворачивает все биты |
<< | Zero fill left shift | Сдвиги влево путем нажатия нулей в справа и пусть левый бит упасть |
>> | Signed right shift | Сдвиг вправо путем нажатия копий левого бита слева, и пусть крайние правая биты падают |
>>> | Zero fill right shift | Сдвиг вправо путем нажатия нулей в слева, и пусть правый биты падать |
Примеры
Операции | Результат | Same as | Результат |
---|---|---|---|
5 & 1 | 1 | 0101 & 0001 | 0001 |
5 | 1 | 5 | 0101 | 0001 | 0101 |
~ 5 | 10 | ~0101 | 1010 |
5 <<1 | 10 | 0101 <<1 | 1010 |
5 ^ 1 | 4 | 0101 ^ 0001 | 0100 |
5>> 1 | 2 | 0101>> 1 | 0010 |
5>>> 1 | 2 | 0101>>> 1 | 0010 |
JavaScript использует битовые операнды 32 бит
JavaScript хранит числа в виде чисел с плавающей запятой в 64 бит, но все битовые операции выполняются с двоичными номерами 32 бит.
До выполнения побитовой операции JavaScript преобразует числа в 32 битов со знаком целых чисел.
После выполнения побитовой операции результат преобразуется обратно в числа JavaScript 64 бит.
В приведенных выше примерах используются 4 бита неподписанных двоичных чисел. Из-за этого ~ 5 возвращает 10.
Поскольку JavaScript использует 32 битов со знаком целых чисел, он не вернет 10. Он вернется-6.
00000000000000000000000000000101 (5)
11111111111111111111111111111010 (~ 5 =-6)
Целое число со знаком использует крайний левый бит в качестве знака минуса.
Побитовое и
При побитовой и выполняется на пару битов, он возвращает 1, если оба бита 1.
Operation | Result |
---|---|
0 & 0 | 0 |
0 & 1 | 0 |
1 & 0 | 0 |
1 & 1 | 1 |
Operation | Result |
---|---|
1111 & 0000 | 0000 |
1111 & 0001 | 0001 |
1111 & 0010 | 0010 |
1111 & 0100 | 0100 |
Побитовое или
При побитовой или выполняется на пару битов, он возвращает 1, если один из б
JavaScript Битовые операторы
JavaScript битовый оператор
Оператор | Название | Описание |
---|---|---|
& | И | Устанавливает каждый бит в 1, если оба бита равны 1 |
| | ИЛИ | Устанавливает каждый бит в 1, если один из двух битов равен 1 |
^ | Исключающее ИЛИ | Устанавливает каждый бит в 1, если только один из двух битов равен 1 |
~ | НЕ | Инвертирует все биты |
<< | Ноль заполнить левый сдвиг | Сдвигает влево, нажимая нули справа, и пусть самые левые биты отключаются |
>> | Знаковый сдвиг вправо | Сдвигает вправо, нажимая копии самого левого бита слева, и пусть самые правые биты отключаются |
>>> | Нулевой сдвиг вправо с заполнением | Сдвигает вправо, нажимая нули слева, и пусть самые правые биты отключаются |
Примеры
Операция | Результат | Так же, как | Результат |
---|---|---|---|
5 & 1 | 1 | 0101 & 0001 | 0001 |
5 | 1 | 5 | 0101 | 0001 | 0101 |
~ 5 | 10 | ~0101 | 1010 |
5 << 1 | 10 | 0101 << 1 | 1010 |
5 ^ 1 | 4 | 0101 ^ 0001 | 0100 |
5 >> 1 | 2 | 0101 >> 1 | 0010 |
5 >>> 1 | 2 | 0101 >>> 1 | 0010 |
JavaScript использует 32-битовые операнды
JavaScript хранит числа как 64-бита, числа с плавающей запятой, но все битовые операции выполняются над 32-битными двоичными числами.
Перед выполнением побитовой операции JavaScript преобразует числа в 32-битные целые числа со знаком.
После выполнения побитовой операции результат преобразуется обратно в 64-битные числа JavaScript.
В приведенных выше примерах используются 4 бита беззнаковых двоичных чисел. Из-за этого ~ 5 возвращает 10.
Поскольку JavaScript использует 32-битные целые числа со знаком, он не вернет 10. Он вернется -6.
00000000000000000000000000000101 (5)
11111111111111111111111111111010 (~5 = -6)
Знаковое целое число использует самый левый бит в качестве знака минус.
Битовый И
Когда побитовое И выполняется на паре битов, она возвращает 1, если оба бита равны 1.
Одно битовый пример:Операция | Результат |
---|---|
0 & 0 | 0 |
0 & 1 | 0 |
1 & 0 | 0 |
1 & 1 | 1 |
Операция | Результат |
---|---|
1111 & 0000 | 0000 |
1111 & 0001 | 0001 |
1111 & 0010 | 0010 |
1111 & 0100 | 0100 |
Битовый ИЛИ
Когда побитовое ИЛИ выполняется на паре битов, оно возвращает 1, если один из битов равен 1:
Одно битовый пример:Операция | Результат |
---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Операция | Результат |
---|---|
1111 | 0000 | 1111 |
1111 | 0001 | 1111 |
1111 | 0010 | 1111 |
1111 | 0100 | 1111 |
Битовый исключающее ИЛИ
Когда побитовое Исключающее ИЛИ выполняется на паре битов, он возвращает 1, если биты отличаются:
Одно битовый пример:Операция | Результат |
---|---|
0 ^ 0 | 0 |
0 ^ 1 | 1 |
1 ^ 0 | 1 |
1 ^ 1 | 0 |
Операция | Результат |
---|---|
1111 ^ 0000 | 1111 |
1111 ^ 0001 | 1110 |
1111 ^ 0010 | 1101 |
1111 ^ 0100 | 1011 |
JavaScript битовый И (&)
Битовый и возвращает 1, только если оба бита равны 1:
Десятичный | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 & 1 | 00000000000000000000000000000001 (1) |
JavaScript битовый ИЛИ ( | )
Битовое ИЛИ возвращает 1, если один из битов равен 1:
Десятичный | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 | 1 | 00000000000000000000000000000101 (5) |
JavaScript битовый исключающий ИЛИ ( ^ )
Битовое исключающий ИЛИ возвращает 1, если биты разные:
Десятичный | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 ^ 1 | 00000000000000000000000000000100 (4) |
JavaScript битовый НЕ ( ~ )
Десятичный | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
~5 | 11111111111111111111111111111010 (-6) |
JavaScript (нулевая заливка) битовый сдвиг влево (<<)
Это смещение влево с нулевым заполнением. Один или несколько нулевых битов нажимаются справа, а самые левые биты отваливаются:
Десятичный | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
5 << 1 | 00000000000000000000000000001010 (10) |
JavaScript (сохранение знака) битовое смещение вправо (>>)
Это знак, сохраняющий сдвиг вправо. Копии самого левого бита выталкиваются слева, а самые правые биты отваливаются:
Десятичный | Двоичный |
---|---|
-5 | 11111111111111111111111111111011 |
-5 >> 1 | 11111111111111111111111111111101 (-3) |
JavaScript (ноль заполнить) сдвиг вправо (>>>)
Это смещение вправо с нулевым заполнением. Один или несколько нулевых битов выталкиваются слева,а самые правые биты отваливаются:
Десятичный | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
5 >>> 1 | 00000000000000000000000000000010 (2) |
Двоичные числа
Двоичный числа числа с одним битовым набором легкий для понимания::
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000001 | 1 |
00000000000000000000000000000010 | 2 |
00000000000000000000000000000100 | 4 |
00000000000000000000000000001000 | 8 |
00000000000000000000000000010000 | 16 |
00000000000000000000000000100000 | 32 |
00000000000000000000000001000000 | 64 |
Установка еще нескольких битов показывает двоичный шаблон:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000101 | 5 (4 + 1) |
00000000000000000000000000001101 | 13 (8 + 4 + 1) |
00000000000000000000000000101101 | 45 (32 + 8 + 4 + 1) |
JavaScript двоичные числа хранятся в формате высокой четкости.
Это означает, что отрицательное число является побитовым НЕ числа плюс 1:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000101 | 5 |
11111111111111111111111111111011 | -5 |
00000000000000000000000000000110 | 6 |
11111111111111111111111111111010 | -6 |
00000000000000000000000000101000 | 40 |
11111111111111111111111111011000 | -40 |
Преобразование десятичного в двоичный
Преобразование двоичного в десятичный
JavaScript побитовые операции
Побитовые операции JavaScript
Оператор | Имя | Описание |
& | AND | Устанавливает для каждого бита значение 1, если оба бита равны 1 |
| | OR | Устанавливает для каждого бита значение 1, если один из двух битов равен 1 |
^ | XOR | Устанавливает для каждого бита значение 1, если только один из двух битов равен 1 |
~ | NOT | Инвертирует все биты |
<< | Zero fill left shift | Сдвигает влево, нажимая нули от правого и пусть левые биты отваливаются |
>> | Signed right shift | Сдвигает вправо, отодвигая копии левого бита слева, и пусть самые правые биты падать |
>>> | Zero fill right shift | Сдвигает вправо, нажимая нули слева, и пусть самые правые биты отваливаются |
Пример
Операция | Результат | Такие же как | Результат |
---|---|---|---|
5 & 1 | 1 | 0101 & 0001 | 0001 |
5 | 1 | 5 | 0101 | 0001 | 0101 |
~ 5 | 10 | ~0101 | 1010 |
5 << 1 | 10 | 0101 << 1 | 1010 |
5 ^ 1 | 4 | 0101 ^ 0001 | 0100 |
5 >> 1 | 2 | 0101 >> 1 | 0010 |
5 >>> 1 | 2 | 0101 >>> 1 | 0010 |
JavaScript использует 32-битные операнды
JavaScript хранит числа как 64-битные числа с плавающей точкой, но все побитовые операции выполняются с 32-битными двоичными числами.
Перед выполнением побитовой операции JavaScript преобразует числа в 32-битные целые числа со знаком.
После выполнения побитовой операции результат преобразуется обратно в 64-разрядные числа JavaScript.
Побитовые «И»
Когда побитовое «И» выполняется для пары битов, оно возвращает 1, если оба бита равны 1.
Один бит:
Операция | Результат |
---|---|
0 & 0 | 0 |
0 & 1 | 0 |
1 & 0 | 0 |
1 & 1 | 1 |
Четыре бита:
Операция | Результат |
---|---|
1111 & 0000 | 0000 |
1111 & 0001 | 0001 |
1111 & 0010 | 0010 |
1111 & 0100 | 0100 |
Побитовые «ИЛИ»
Когда по паре битов выполняется побитовое ИЛИ, возвращается 1, если один из битов равен 1:
Один бит:
Операция | Результат |
---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Четыре бита:
Операция | Результат |
---|---|
1111 | 0000 | 1111 |
1111 | 0001 | 1111 |
1111 | 0010 | 1111 |
1111 | 0100 | 1111 |
Побитовое XOR
Если на паре битов выполняется побитовое XOR, то возвращается 1, Если биты разные:
Один бит:
Операция | Результат |
---|---|
0 ^ 0 | 0 |
0 ^ 1 | 1 |
1 ^ 0 | 1 |
1 ^ 1 | 0 |
4 бита:
Операция | Результат |
---|---|
1111 ^ 0000 | 1111 |
1111 ^ 0001 | 1110 |
1111 ^ 0010 | 1101 |
1111 ^ 0100 | 1011 |
JavaScript побитовый и (&)
И возвращает 1 только если оба бита равны 1:
Десятичное число | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 & 1 | 00000000000000000000000000000001 (1) |
JavaScript побитовый или (|)
Или (|) возвращает 1, если один из битов равен 1:
Десятичное число | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 | 1 | 00000000000000000000000000000101 (5) |
JavaScript побитовое XOR (^)
Побитовый XOR возвращает 1, если биты разные:
Десятичное число | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 ^ 1 | 00000000000000000000000000000100 (4) |
JavaScript Побитовое не (~)
Десятичное число | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
~5 | 11111111111111111111111111111010 (-6) |
JavaScript (Zero Fill) Побитовый Сдвиг Влево (<<)
Это смещение нуля влево. Один или несколько нулевых битов вставляются справа, и самые левые биты падают:
Десятичное число | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
5 << 1 | 00000000000000000000000000001010 (10) |
JavaScript (Сохранение Знака) Побитовый Сдвиг Вправо (>>)
Это знак сохранения правого сдвига. Копии самого левого бита вставляются слева, а самые правые биты падают:
Десятичное число | Двоичный |
---|---|
-5 | 11111111111111111111111111111011 |
-5 >> 1 | 11111111111111111111111111111101 (-3) |
JavaScript (Zero Fill) Сдвиг Вправо (>>>)
Это смещение нуля вправо. Один или несколько нулевых битов вводятся слева, а самые правые биты падают:
Десятичное число | Двоичный |
---|---|
5 | 00000000000000000000000000000101 |
5 >>> 1 | 00000000000000000000000000000010 (2) |
Двоичные числа
Двоичные числа с одним битовым набором легко понять:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000001 | 1 |
00000000000000000000000000000010 | 2 |
00000000000000000000000000000100 | 4 |
00000000000000000000000000001000 | 8 |
00000000000000000000000000010000 | 16 |
00000000000000000000000000100000 | 32 |
00000000000000000000000001000000 | 64 |
Установка еще нескольких битов показывает двоичный шаблон:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000101 | 5 (4 + 1) |
00000000000000000000000000001101 | 13 (8 + 4 + 1) |
00000000000000000000000000101101 | 45 (32 + 8 + 4 + 1) |
Двоичные числа JavaScript хранятся в двух дополнительных форматах.
Это означает, что отрицательное число является побитовым не числа плюс 1:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000101 | 5 |
11111111111111111111111111111011 | -5 |
00000000000000000000000000000110 | 6 |
11111111111111111111111111111010 | -6 |
00000000000000000000000000101000 | 40 |
11111111111111111111111111011000 | -40 |
javascript — Какие битовые операции?
Так как никто не поднял вопрос о том, почему они полезны:
Я использую битовые операции много при работе с флагами. Например, если вы хотите пройти ряд флагов операции (скажем, File.open, в режиме чтения и режим и включен запись), вы можете передать их в качестве одного значения. Это достигается путем присвоения каждому возможного флага его собственный бит в BitSet (байт, короткие, Int, или длинной). Например:
Read: 00000001
Write: 00000010
Так что если вы хотите передать читать и писать, вы бы передать (ЧИТАТЬ | WRITE), который затем сочетает в себе два в
00000011
Что может быть расшифрован на другом конце, как:
if ((flag & Read) != 0) { //...
который проверяет
00000011 &
00000001
которая возвращает
00000001
который не является 0, так что флаг действительно указать READ.
Вы можете использовать XOR для переключения различных бит. Я использовал это при использовании флага для указания направления входа (вверх, вниз, влево, вправо). Например, если спрайт движется горизонтально, и я хочу, чтобы развернуться:
Up: 00000001
Down: 00000010
Left: 00000100
Right: 00001000
Current: 00000100
Я просто XOR текущее значение с (слева | справа), который будет повернуть налево от и ВПРАВО, в этом случае.
Бито Shifting полезно в ряде случаев.
x << y
такой же как
х * 2 у
если вам нужно быстро умножить на степени двойки, но следить за сдвиг 1 бит в верхний бит — это делает число отрицательным, если это не без знака. Это также полезно при работе с различными размерами данных. Например, чтение целого числа от четырех байт:
int val = (A << 24) | (B << 16) | (C << 8) | D;
Предполагая, что является наиболее значащими байтами и 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. Таким образом, по существу, для красного цвета, вы будете делать это:
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)
javascript — Битовые операции над строками в JavaScript
В JavaScript, когда строка используется с бинарным оператором он сначала преобразуется в число. Соответствующие части спецификации ECMAScript приведены ниже, чтобы объяснить, как это работает.
Битовые операторы :
Производство A: @ B, где @ является одним из битовых операторов в вышеперечисленных правилах, вычисляется следующим образом:
- Пусть LRef быть результатом вычисления A.
- Пусть lval быть ПолучитьЗначение (LRef).
- Пусть RREF быть результатом оценки B.
- Пусть RVal быть ПолучитьЗначение (RREF).
- Пусть lnum быть ToInt32 (lval).
- Пусть rnum быть ToInt32 (RVAL).
- Возвращает результат применения побитового оператора @ к lnum и rnum. Результат является знаковым 32-битным целым числом.
ToInt32 :
Абстрактная операция ToInt32 преобразует свой аргумент к одному из 2 32 целых значений в диапазоне от -231 через 231-1, включительно. Эта абстрактная операция выполняет следующие функции:
- Пусть номер будет результатом вызова ToNumber входного аргумента.
- Если число равно NaN, +0, -0, + ∞ или -∞, вернуть +0.
- Пусть posInt будет знак (номер) * пол (абс (номер)).
- Пусть int32bit быть posInt по модулю 2 32 ; то есть конечное целое значение K типа Number с положительным знаком и менее чем 2 32 по величине таким образом, что математическая разность posInt и к математически целое число , кратное 2 32 .
- Если int32bit больше или равно 2 31 , возвращают int32bit — 2 32 , в противном случае возвращают int32bit.
Внутренняя функция ToNumber возвратит NaN для любой строки , которая не может быть разобрана как число, и ToInt32 (NaN) даст 0. Таким образом , в вашем примере коды все поразрядных операторов с буквами как операнды будут вычисляться 0 | 0
, что объясняет , почему только 0 печатается.
Обратите внимание , что — то вроде '7' | '8'
будет вычисляться , 7 | 8
так как в этом случае строка , используемая в качестве операндов может быть успешно convered к ряду.
А почему поведение в Python отличается, есть на самом деле не какой — либо неявное преобразование типа в Python , так ошибка , как ожидается , для любого типа , который не реализует бинарных операторов (с помощью __or__
, __and__
и т.д.), и строки не реализовать эти бинарные операторы.
Perl делает нечто совершенно иное, битовые операторы выполняются для строк , и он будет по существу выполнять оператор побитового для соответствующих байтов из каждой строки.
Если вы хотите использовать JavaScript и получить тот же результат , как Perl, вам нужно сначала преобразовать символы в их кодовых точки , используя str.charCodeAt
, выполнять оператор побитового на результирующих числах, а затем использовать String.fromCodePoint
для преобразования полученных числовых значений в символы.
Необычное использование побитового XOR в Javascript? — Хабр Q&A
Привет.Отлаживая недавно очередной кусок чужого кода наткнулся на такой цикл:
while (--i ^ -1) /* тело цикла */;
при этом, изначально i равно некоторому положительному числу. То есть, побитовый оператор используется здесь для целых чисел. Немного подумав, я понял, что результат побитового XOR обратится в нуль единственно в случае, когда числа равны. Тогда условие кастуется в true. В противном случае, будет не-ноль, что кастуется в false.
Получается, можно использовать побитовый XOR вместо оператора != (если мы заранее знаем, что сравниваемые величины суть числа).
Отсюда у меня возник вопрос, который я хочу поставить перед аудиторией.
Почему автор использует XOR?
Вчера весь вечер я размышлял над этим и наиболее правдоподобной причиной мне показалось желание написать «крутой непонятный код». Сразу вспомнилось, как я, когда начинал постигать азы программирования, вдруг обнаружил, что могу писать «лаконичный код, который сложен для понимания и который работает». Мне казалось, что это свидетельствует о каких-то скиллах. На самом деле, понятно, что это свидетельствует об обратном. В пользу этой гипотезы было ещё то, что весь остальной код в окрестности приведённого фрагмента был написан подобным образом.
Правда, мне не давала покоя ещё одна мысль. Я представил себе, что если бы я хотел усложнить код, мне бы почему-то не пришло в голову использовать XOR, даже если бы я и знал о такой возможности.
В результате (безуспешно пытаясь заснуть на протяжение двух часов 🙂 ), я встал, подошёл к компу и написал скриптик, который делал много сравнений тем и иным способом и мерял время.
Оказалось, что если использовать побитовый XOR вместо !=, появляется прирост в производительности (по крайней мере на Firefox), этот прирост стабильный (то есть он есть всегда, то больше, то меньше), но составляет всего лишь около 1%.
Может быть, есть ещё какие-нибудь особенности, дающие преимущество побитовому XOR?