Js битовые операции: Побитовые операторы – Битовые операции — JavaScript | MDN

Содержание

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.

One bit example:
OperationResult
0 & 0
0
0 & 10
1 & 00
1 & 11
4 bits example:
OperationResult
1111 & 00000000
1111 & 00010001
1111 & 00100010
1111 & 01000100

Побитовое или

При побитовой или выполняется на пару битов, он возвращает 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 & 00
0 & 10
1 & 00
1 & 11
Четырех битовый пример:
ОперацияРезультат
1111 & 00000000
1111 & 00010001
1111 & 00100010
1111 & 01000100

Битовый ИЛИ

Когда побитовое ИЛИ выполняется на паре битов, оно возвращает 1, если один из битов равен 1:

Одно битовый пример:
ОперацияРезультат
0 | 00
0 | 1
1 | 01
1 | 11
Четырех битовый пример:
ОперацияРезультат
1111 | 00001111
1111 | 00011111
1111 | 00101111
1111 | 01001111

Битовый исключающее ИЛИ

Когда побитовое Исключающее ИЛИ выполняется на паре битов, он возвращает 1, если биты отличаются:

Одно битовый пример:
ОперацияРезультат
0 ^ 00
0 ^ 1
1 ^ 01
1 ^ 1
Четырех битовый пример:
ОперацияРезультат
1111 ^ 00001111
1111 ^ 00011110
1111 ^ 00101101
1111 ^ 01001011

JavaScript битовый И (&)

Битовый и возвращает 1, только если оба бита равны 1:

ДесятичныйДвоичный
500000000000000000000000000000101
100000000000000000000000000000001
5 & 100000000000000000000000000000001 (1)

JavaScript битовый ИЛИ ( | )

Битовое ИЛИ возвращает 1, если один из битов равен 1:

ДесятичныйДвоичный
500000000000000000000000000000101
100000000000000000000000000000001
5 | 100000000000000000000000000000101 (5)

JavaScript битовый исключающий ИЛИ ( ^ )

Битовое исключающий ИЛИ возвращает 1, если биты разные:

ДесятичныйДвоичный
500000000000000000000000000000101
100000000000000000000000000000001
5 ^ 100000000000000000000000000000100 (4)

JavaScript битовый НЕ ( ~ )

ДесятичныйДвоичный
500000000000000000000000000000101
~511111111111111111111111111111010 (-6)

JavaScript (нулевая заливка) битовый сдвиг влево (<<)

Это смещение влево с нулевым заполнением. Один или несколько нулевых битов нажимаются справа, а самые левые биты отваливаются:

ДесятичныйДвоичный
500000000000000000000000000000101
5 << 100000000000000000000000000001010 (10)

JavaScript (сохранение знака) битовое смещение вправо (>>)

Это знак, сохраняющий сдвиг вправо. Копии самого левого бита выталкиваются слева, а самые правые биты отваливаются:

ДесятичныйДвоичный
-511111111111111111111111111111011
-5 >> 111111111111111111111111111111101 (-3)

JavaScript (ноль заполнить) сдвиг вправо (>>>)

Это смещение вправо с нулевым заполнением. Один или несколько нулевых битов выталкиваются слева,а самые правые биты отваливаются:

ДесятичныйДвоичный
500000000000000000000000000000101
5 >>> 100000000000000000000000000000010 (2)

Двоичные числа

Двоичный числа числа с одним битовым набором легкий для понимания::

Двоичное представлениеДесятичное значение
000000000000000000000000000000011
000000000000000000000000000000102
000000000000000000000000000001004
000000000000000000000000000010008
0000000000000000000000000001000016
0000000000000000000000000010000032
0000000000000000000000000100000064

Установка еще нескольких битов показывает двоичный шаблон:

Двоичное представлениеДесятичное значение
000000000000000000000000000001015 (4 + 1)
0000000000000000000000000000110113 (8 + 4 + 1)
0000000000000000000000000010110145 (32 + 8 + 4 + 1)

JavaScript двоичные числа хранятся в формате высокой четкости.

Это означает, что отрицательное число является побитовым НЕ числа плюс 1:

Двоичное представлениеДесятичное значение
000000000000000000000000000001015
11111111111111111111111111111011-5
000000000000000000000000000001106
11111111111111111111111111111010-6
0000000000000000000000000010100040
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, где @ является одним из битовых операторов в вышеперечисленных правилах, вычисляется следующим образом:

  1. Пусть LRef быть результатом вычисления A.
  2. Пусть lval быть ПолучитьЗначение (LRef).
  3. Пусть RREF быть результатом оценки B.
  4. Пусть RVal быть ПолучитьЗначение (RREF).
  5. Пусть lnum быть ToInt32 (lval).
  6. Пусть rnum быть ToInt32 (RVAL).
  7. Возвращает результат применения побитового оператора @ к lnum и rnum. Результат является знаковым 32-битным целым числом.

ToInt32 :

Абстрактная операция ToInt32 преобразует свой аргумент к одному из 2 32 целых значений в диапазоне от -231 через 231-1, включительно. Эта абстрактная операция выполняет следующие функции:

  1. Пусть номер будет результатом вызова ToNumber входного аргумента.
  2. Если число равно NaN, +0, -0, + ∞ или -∞, вернуть +0.
  3. Пусть posInt будет знак (номер) * пол (абс (номер)).
  4. Пусть int32bit быть posInt по модулю 2 32 ; то есть конечное целое значение K типа Number с положительным знаком и менее чем 2 32 по величине таким образом, что математическая разность posInt и к математически целое число , кратное 2 32 .
  5. Если 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?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *