Побитовые операторы
Прямой, обратный и дополнительный код числа
http://www.reshinfo.com/dopolnit_code.php
Перевод в разные системы счислений
Перевести число из десятичной в другую систему счисления позволяет функция .toString(n); где n - основание системы счисления
(7).toString(2); // "111"
Перевод числа в десятичную систему счисления - функция parseInt("...", m), где m указывает из какой системы осуществляется перевод в десятичную
parseInt(111, 2); // 7
Перевести число из любой системы m в любую систему n позволяет комбинация этих двух функций
parseInt("...", m).toString(n);
Например, переведём 111 из двоичной системы в троичную
parseInt(111, 2).toString(3); // 21
Функция .toString(n); переводит только числа и возвращает строку, функция parseInt("...", m); принимает и числа и строки и возвращает число.
Побитовые операторы
Оператор | Использование | Описание |
---|---|---|
Побитовое И (AND) | a & b |
Ставит 1 на бит результата, для которого соответствующие биты операндов равны 1. |
Побитовое ИЛИ (OR) | a | b |
Ставит 1 на бит результата, для которого хотя бы один из соответствующих битов операндов равен 1. |
Побитовое исключающее ИЛИ (XOR) | a ^ b |
Ставит 1 на бит результата, для которого только один из соответствующих битов операндов равен 1 (но не оба). |
Побитовое НЕ (NOT) | ~a |
Заменяет каждый бит операнда на противоположный. |
Левый сдвиг | `a << b` | Сдвигает двоичное представление a на b битов влево, добавляя справа нули. |
Правый сдвиг, переносящий знак | `a >> b` | Сдвигает двоичное представление a на b битов вправо, отбрасывая сдвигаемые биты. |
Правый сдвиг с заполнением нулями | `a >>> b` | Сдвигает двоичное представление a на b битов вправо, отбрасывая сдвигаемые биты и добавляя нули слева. |
Зачем нужны побитовые операторы?
Ну, во-первых. они работают быстрее. Намного быстрее. В разы.
Битовый сдвиг работает быстрее умножения, html5 canvas использует побитовые операторы.
Округление при помощи побитового ИЛИ работает вдвое шустрее Math.floor http://javascript.ru/bitwise-operators
( 100 / 3 ) | 0; // 33
А нужны ли тут скобки? Смотрим приоритет операторов деление - 14, побитовое ИЛИ - 7.
То есть деление и так выполнится раньше, скобки не нужны для управления последовательностью действий, но, возможно, улучшают читабельность кода, особенно если таблицу приоритетов наизусть не выучил.
& (Побитовое И)
14 & 9 // 8
14
8 + 4 + 2
1110
9
8 + 0 + 0 +1
1001
1110
1001
1000 – 8
________________
| (Побитовое ИЛИ)
14 | 9 // 15
1110
1001
1111 – 15
^ (Исключающее ИЛИ)
14 ^ 9 // 7
1110
1001
0111 – 7
7 ^ 9 // 14
0111
1001
1110 - 14
В общем виде справедлива формула
a ^ b ^ b == a
Это позволяет использовать исключающее ИЛИ для шифрования.
Если предположить, что а - данные, которые нужно зашифровать, а b - ключ, который есть у обеих сторон, то дважды применив исключающее ИЛИ получим исходный текст.
Для чего можно использовать побитовые операторы
1) округление чисел
~~6.354; // 6
6.354 ^ 0; // 6
2) Быстрое умножение или деление на 2 в степени n, которое выполняется в один такт.
9 >> 1 // 4, потому что сдвинуть на один бит вправо всё равно что разделить на два в первой степени, а потом округлить до целого
4 << 3 // 32 потому что 4 * 2^3 = 4 * 8 = 32
3) проверка на -1
Чтобы сменить знак числа на противоположный нужно изменить каждый его бит на противоположный (побитовое НЕ) и прибавить единицу.
~n + 1 = -n , откуда ~ n = -n + 1
Таким образом ~n = 0 только если n = -1.
Это значение можно добавить в условие if ( ~n ) { .. }, которое будет выполняться только если n не равно -1. Такая возможность полезна для тех функций, которые возвращают -1 в случае отсутствия результата. Например, indexOf() возвращает первое вхождение подстроки в строку, или -1.
str.indexOf("подстрока")
"ля-ля-ля".indexOf("оля") // -1
4) проверка чётное число или нечётное
В двоичном представлении нечётных чисел последняя цифра справа всегда единица. Применение побитового И с единицей для нечётных чисел даёт 1, для чётных 0:
11 & 1 // 1
12 & 1 // 0
5) c помощью исключающего ИЛИ ^ можно поменять значения двух переменных (имеющих одинаковый тип данных) без использования временной переменной.
function swapper(a, b) {
a = b ^ a; // заменяет временную переменную, которая не равна ни а, ни b, но из которой их легко получить
b = a ^ b; // получается b = b ^ a ^ b => а
a = a ^ b; // получается a = b ^ a ^ a => b
return [a, b]
}
6) побитовое НЕ плюс единица меняют знак числа
~n + 1 // -n
7) конечно же побитовые маски, когда у каждого объекта есть куча свойств (но не больше 32, числа ведь используются 32-битные) и нужно их определить или на них повлиять
Дополнительно: Хитрости с битовыми операциями
Дополнено
В обсуждении задали вопрос
Что быстрее работает: a^0 или ~~a?
Проверить скорость работы можно на сайте https://jsperf.com/bitwise-operators-speed (это уже созданный тест)
Его результаты
То есть ни о каких выигрышах в 65% или 36% речи не идёт. Разница в скорости составляет доли процента и зависит от браузера. Но ~~a всё-таки немного быстрее.
UPD Терплю это "безобразие" уже несколько страниц, но сил уже не осталось. Не нужно проверять число на чётность с помощью '%'. Эта операция занимает довольно много тактов процессора. Гораздо проще (и в смысле читаемости тоже) и уж точно быстрее использовать побитовое и '&'. Например так.
if ( n & 1) // число нечётное
источник