Javascript исключающее или
Побитовые операторы
Побитовые (поразрядные) операторы & , | , ^ и
напоминают логические операторы, но их область действия — биты, а не логические значения. Среди побитовых операторов есть также операторы сдвига, позволяющие переместить все биты числа влево или вправо на нужно количество разрядов.
Формат 32-битного целого числа со знаком
Поразрядные (побитовые) операторы работают с 32-битными целыми числами в их двоичном представлении.
Двоичные числа представляют из себя строки, состоящие из нулей и единиц, в которых значение каждой единицы определяется ее позицией в данной строке.
Вот так, например, выглядият числа, записанные в формате 32-разрядного целого двоичного числа:
Каждый сдвиг влево на одну позицию означает удвоение значения, которое соответствует предыдущей позиции, находящейся справа.
Чтобы не путать, в какой системе счисления записано число, обычно в индексе пишут основание системы счисления, в которой оно записао. Например, число 5 в десятичной системе – 510,а в двоичной – 1012.
Чтобы перевести число в двоичную систему счисления необходимо делить его нацело на 2 пока не получим , затем необходимо записать все остатки от деления в обратном порядке.
Например, число 18, записываемое в двоичной системе счисления, имеет значение:
Теперь записываем полученные остатки от деления в обратном порядке. Получаем, что число 18 в двоичном представлении будет выглядеть как 00000000000000000000000000010010 (обратите внимание, число состоит ровно из 32-битов), или, сокращенно, как 10010. Эти пять значимых битов и определяют фактическое значение числа 18.
Для преобразования из двоичной системы в десятичную используют формулу, состоящую из степеней основания 2:
где а – число в десятичной системе счисления; a, a1, … an – цифры данного числа в двоичном представлении. Причём a — это последняя или правая цифра, а an – первая.
Например, возьмём двоичное число 1010012. Для перевода в десятичное запишем его как сумму по разрядам следующим образом:
Перепишем тоже самое, возведя в степени все основания 2:
Можно записать это в виде таблицы следующим образом:
Положительные числа хранятся в настоящем двоичном формате, в котором все биты, кроме знакового (крайний левый), представляют степени двойки: первый бит (справа) соответствует 2 0 , второй – 2 1 , третий – 2 2 и т. д. Если какие-либо биты не используются, они считаются равными нулю.
Теперь под каждой двоичной единицей напишите её эквивалент в нижней строчке таблицы и сложите получившиеся десятичные числа. Таким образом, двоичное число 1010012 равнозначно десятичному 4110.
Термин «целые числа со знаком» означает, что в этой форме могут быть представлены как положительные, так и отрицательные целые числа.
Отрицательные числа также хранятся в двоичном коде, но в формате, который называется «дополнителъным кодом» (англ. two’s complement, иногда twos-complement).
Представление в «дополнительном коде» означает, что отрицательное значение числа (например 5 и -5) получается путем инвертирования числа (операция «побитовое НЕ», также известное как «обратный код» или «первое дополнение») и прибавлением к инверсии единицы («второе дополнение»).
К примеру, определим двоичное представление числа -5. Начнём с двоичного представления его абсолютного значения (5):
Инвертируем все разряды числа (заменим на 1, а 1 на ), получая таким образом обратный код (первое дополнение) числа 5:
Дополнительный код (второе дополнение) двоичного числа получается добавлением 1 (обычным двоичным сложением) к младшему значащему разряду его первого дополнения:
Итак, мы получили:
В целых числах со знаком все биты, кроме 32-го, представляют само значение, тогда как 32-й бит определяет знак числа: если крайний-левый бит равен – число положительное, если 1 – число отрицательное. Поэтому этот бит называется знаковым битом.
Однако в JavaScript такое двоичное представление чисел скрыто. Например, при выводе отрицательного числа в виде двоичной строки вы получите сокращенный двоичный код абсолютного значения этого числа со знаком «минус»:
При изучении побитовых операторов вам могут пригодиться функции, которые облегчают перевод чисел из десятичного в двоичное представление и наоборот:
Список побитовых операторов
В следующей таблице перечислены все побитовые (поразрядные) операторы JavaScript:
Побитовые операторы, подобно логическим операторам, выполняют логические операции И, ИЛИ, НЕ, XOR , но с каждым отдельным битом целого числа. Cреди побитовых операторов есть также операторы сдвига >, >>> позволяющие переместить все биты числа влево или вправо на нужно количество разрядов. Побитовые операторы преобразуют свои операнды в 32-битные целые числа, представленные последовательностью битов. Дробная часть, если она есть, отбрасывается. Получившаяся в результате выполнения последовательность бит интерпретируется как обычное число.
Побитовое И (&)
Таблица истинности для этой операции выглядит так:
В следующем примере поразрядное И выполняется для чисел 38 и 3:
Как видите, только в одной позиции биты обоих операндов равны 1. Из-за этого все остальные биты результата обнуляются, что в итоге дает 000010. Как результат, получаем 0000102, или 210.
Побитовое ИЛИ (|)
Побитовое ИЛИ ( | ) выполняет булеву операцию дизъюнкции над каждой парой битов, которые стоят на одинаковых позициях в двоичных представлениях операндов. Другими словами, результат a | b равен , если оба соответствующих бита операндов равны ; если же хотя бы один бит из пары равен 1, результирующий двоичный разряд равен 1.
Таблица истинности для этой операции выглядит так:
В следующем примере поразрядное ИЛИ выполняется для чисел 38 и 3:
Каждый единичный бит любого из операндов переходит в результат. В итоге, получаем 1001112, или 3910.
Побитовое исключающее ИЛИ (^)
Побитовое исключающее ИЛИ ( ^ ) выполняет исключающую дизъюнкцию над каждой парой битов, которые стоят на одинаковых позициях в двоичных представлениях операндов. Другими словами, результат a ^ b равен , если оба соответствующих бита операндов равны между собой; в противном случае, двоичный разряд результата равен 1.
Таблица истинности для этой операции выглядит так:
В следующем примере поразрядное исключающее ИЛИ выполняется для чисел 38 и 3:
Этот пример отличается от предыдущего только тем, что второй бит результата обнуляется, поскольку в обоих операндах он равен 1. Все остальные единичные биты переходят в результат, потому что у них нет пары. В итоге, получаем 1001012, или 3710.
Исключающее ИЛИ ( ^ ) с нулём в качестве одного из операндов можно использовать для округления математических выражений:
Учитывая, что у побитовых операторов достаточно низкий приоритет (ниже чем у арифметических операторов), скобки в приведенных выражениях могут быть опущены.
Побитовое НЕ (
Побитовое отрицание НЕ (
) – это унарный оператор, который возвращает обратный код числа. Другими словами, на той позиции, где в двоичном представлении операнда был , в результате будет 1, и, наоборот, где была 1, там будет .
Таблица истинности для этой операции выглядит так:
В следующем примере операция НЕ выполняется для числа 52:
По сути, число просто инвертируется, а затем новое значение уменьщается на 1.
Тот же результат можно получить следующим образом:
Учитывая тот факт, что битовые операции отбрасывают десятичную часть, их можно использовать для округления чисел.
Например, двойное НЕ (
) позволяет округлить числа до целых значений:
Сдвиг битов влево ( ) перемещает влево все биты первого операнда на расстояние, заданное вторым операндом (целое число в диапазоне от 0 до 31). При сдвиге битов влево освободившиеся разряды справа заполняются нулями.
Например, если сдвинуть число 2 (10 в двоичном формате) на 5 битов влево, получится 64 (1000000 в двоичном формате):
В этом примере, при сдвиге числа влево на пять битов, справа пять пустых битов заполняются нулями, чтобы в результате получилось полное 32-разрядное число.
На заметку: Побитовый сдвиг влево на N позиций эквивалентен умножению числа на 2 N . Таким образом, 4 .
Тот же результат, что и в предыдущем примере, можно получить следующим образом:
Хотя результаты одинаковы, поразрядные операторы выполняется гораздо быстрее, потому что они работает на самом низком уровне. Поэтому их использование, вместо математических функций, обеспечит неплохой прирост производительности.
Сдвиг битов вправо с сохранением знака (>>)
Оператор >> (сдвиг битов вправо с сохранением знака) в точности противоположен сдвигу влево. Слева от оператора >> указывается операнд, биты которого будут сдвинуты, а справа – целое число в диапазоне от 0 до 31, которое определяет на сколько разрядов вправо будут сдвинуты биты операнда.
Если операнд положительный, то пустые места слева заполняются нулями. Если же изначально мы работаем с отрицательным числом, то все пустые места заполняются единицами. Это делается для сохранения знака, представленного крайним-левым битом. Поэтому он назван «переносящим знак».
В следующем примере выполняется сдвиг битов вправо на 2 разряда для чисел 9 и -9:
На заметку: Побитовый сдвиг вправо на N позиций эквивалентен делению этого числа на 2 N . Побитовый сдвиг выполняется намного быстрее обычного деления.
Сдвиг битов вправо с заполнением нулями (>>>)
Оператор >>> (сдвиг битов вправо с заполнением нулями) сдвигает все биты числа вправо на указанное количество разрядов. В отличие от сдвига вправо с сохранением знака >> , теперь пустые слева биты заполняются нулями независимо от знака числа. Знаковый бит становится равным 0 , поэтому результат всегда положителен.
В следующем примере выполняется сдвиг битов вправо на 2 разряда для чисел 9 и -9:
При сдвиге вправо с заполнением нулями отрицательное число в двоичном формате обрабатывается как положительное число. Учитывая, что отрицательное число является дополнением его абсолютного значения до двух, число становится очень большим, например, результатом -9 >>> 2 будет 1073741821 в десятичном формате.
Итоги
- Побитовые операторы работают с числами на самом низком уровне – уровне отдельных битов, поэтому в JavaScript они выполняются гораздо быстрее, чем другие операторы или методы.
- Специальные значения NaN и Infinity в поразрядных операциях интерпретируются как О.
- Если побитовые операторы применяются к нечисловому значению, то оно сначало автоматически преобразуется в число с помощью функции Number() и только затем выполняется операция.
- Побитовое НЕ
просто инвертирует все биты операнда, а затем новое значение уменьшает на 1.
С помощью двух побитовых НЕ
можно округлить значение операнда или математического выражения.
Задачи
Какое из двух выражений истинно?
Поскольку у оператора сложения более высокий приоритет, чем у оператора сдвига, правильный ответ: а >> b + 7 == а >> (b + 7). Так что если вам требуется выполнить операцию (а>>b) + 7, то без скобок не обойтись.
JS для начинающих. Урок 1.8: Логические и побитовые операторы
Автор: Антон Кургузенков
Дата записи
Логические операторы
Логические операторы, так же как и арифметические могут быть бинарными и унарными, но в отличие от арифметических возвращённое ими значение чаще всего рассматривается как логическое.
Замечание:
Обратите внимание на то, что в js значение, возвращаемое логическими операторами, не всегда имеет логический тип (равно true или false). В этом уроке мы рассмотрим только те случаи, когда возвращаемое значение имеет логический тип.
Оператор отрицания
Единственной унарным логическим оператором является оператор отрицания (!). Применённый к переменной, содержащей значение true, он возвращает false, и наоборот.
var a = true; alert(!a); // покажет в сером унылом окошке false a = !a; alert(a); // снова false
Напоминаю, что для ваших экспериментов с js идеально подходит консоль. Если убрать из предыдущих примеров функция alert, то можно построчно вводить их в консоль и наблюдать за значением, которое возвращает вводимая вами строка.
Операторы равенства и неравенства
Здесь мы рассмотрим только оператор == и случай, когда оба операнда имеют одинаковый тип и являются строками, числами или логическими значениями. Существует ещё и оператор ===, и операнды у операторов == и === могут иметь различные типы, но об этом мы поговорим позже.
Итак, оператор == сравнивает два значения и возвращает true, если они равны и false, если нет.
var a = 123, b = 123 a == b; // вернёт true a = 321; a == b; // false a = b; a == b; // снова true
С текстовыми значениями абсолютно так же.
var str1 = «string», str2 = «string»; str1 == str2; // true str1 == ‘another string’; // false
Оператор неравенства (!=) возвращает значение противоположное тому, которое вернул бы оператор равенства.
var a = 123, b = 123 a != b; // вернёт false a = 321; a != b; // true a = b; a != b; // сново false
Операторы сравнивания
Эти операторы служат для сравнивания чисел, но в js их можно использовать для сравнивания абсолютно чего угодно, при этом, правда, вряд ли можно будет назвать результат осмысленным, так как неизвестно что больше килограмм или метр.
Операторы сравнивания это бинарные операторы «больше» и «меньше» («>»,« =»,« b); // false console.log(a = b); // false a = 2; b = 2; console.log(a = b); // true
Логическое «или» и логическое «и»
Оператор логическое «или» выглядит, как || и возвращает true тогда и только тогда, когда хотя бы один из операндов равен true.
var a = true, b = false; a || b; // true a = b; a || b; // false a = true; b = true; a || b; // true;
Оператор логическое «и» (&&) возвращает true тогда и только тогда, когда оба его операнда равны true.
var a = true, b = true; a && b; // true a = false; a && b; // false b = false; a && b; // false;
Приоритеты логических операций
Аналогично арифметическим операторам, некоторые логические операторы имеют приоритет над другими, то есть выполняются раньше. Чтобы запомнить, что выполняется раньше, логическое «или» (||) или логическое «и» (&&), можно сопоставить оператору || сложение, а оператору && умножение. Действительно, в этом есть смысл, если считать что истина (true) это 1, a ложь (false) это 0, то 1 || 0 = 1 = 1 + 0, 0 || 0 = 0 = 0 + 0, 1 && 0 = 0 = 1 * 0, 0 && 0 = 0 = 0 * 0, 1 && 1 = 1 = 1 * 1. Единственный нюанс это что 1 || 1 = 1 так как третьего логического значения (2) нет.
У сложения, которое мы сравнили с оператором (||) приоритет ниже, чем у умножения, которое мы сравниваем с оператором &&, поэтому && выполняется раньше чем ||. Для того, чтобы установить другой порядок выполнения логических операций используйте скобки. Пример:
var a = true, b = false; a || b && b; // true (a || b) && b; // false
В первом логическом выражении оператор && выполнился раньше, чем ||. Во втором выражении — наоборот.
Побитовые операторы
Эти операторы редко используются при написании скриптов, но знать о них всё же стоит. Кто знает, какие задачи вам придётся решать с помощью js.
Чтобы понять, как работают побитовые операторы, нам придётся научиться переводить их операнды в двоичную систему счисления. Чтобы перевести число в двоичную систему счисления необходимо делить его нацело на 2 пока не получится 0, запоминая остатки от деления, затем записать их в обратном порядке. Например («/» означает деление нацело):
30 / 2 = 15 остаток 0
15 / 2 = 7 остаток 1
7 / 2 = 3 остаток 1
3 / 2 = 1 остаток 1
1 / 2 = 0 остаток (обратите внимание!) 1
А теперь записываем остатки от деления, собирая их снизу вверх. Получаем, что 30 в двоичном представлении будет выглядеть как 11110. Чтобы поставить знак равенства между числами в разных системах счисления, обычно в индексах у них пишут основание системы счисления, в которой они записаны.
Нам также полезно будет знать, как переводить числа назад из двоичной в десятичную систему счисления. Осуществить подобную операцию можно по формуле:
a = a * 2 0 + a1 * 2 1 + a2 * 2 2 + … + an * 2 n
Где а – число в десятичной системе счисления; a, a1, … an – цифры этого числа в двоичном представлении. Причём a — это последняя цифра, а an – первая.
Например, переведём число 1010012 в десятичную систему счисления.
1010012 = 1 * 2 0 + 0 * 2 1 + 0 * 2 2 + 1 * 2 3 + 0 * 2 4 + 1 * 2 5 = 1 + 8 + 32 = 4110
Теперь у вас достаточно знаний для того, чтобы понять, как работают побитовые операторы.
Рассмотрим оператор побитовое «или» ( | ). Этот оператор производит операцию логического «или» над соответствующими битами (разрядами в двоичном представлении операндов), помещая результат в соответствующий разряд двоичного представления результата. При этом значению true соответствует 1, false – 0. Например:
7 | 9; // вернёт 15
7 имеет двоичное представление 111, а 9 – 1001. Запишем эти двоичные значения друг под другом (доставим при этом перед 111 ноль, чтобы сравнять их длину) выполним операции логического «или» над разрядами, которые находятся друг под другом, и запишем результат под ними.
1111 это двоичное представление числа 15
Теперь рассмотрим побитовое «и». Оно работает аналогично, только над битами операндов производится операция логического и
Есть и ещё операция побитового отрицания (
) она заменяет в двоичном представлении операнда 0 на 1, а 1 на 0. Так как первый бит у числа знаковый, то знак у результата будет противоположным знаку операнда. Фактически этот операнд работает как выражение –n – 1.
Теперь ознакомимся с такой побитовой операцией как xor или «исключающие или». Это операция ставит в соответствующую позицию результата в двоичном представлении 0, если биты на соответствующих позициях в операндах одинаковы, и 0 в противном случае. В js это операция может быть выполнена при помощи символа «^». Например, поксорим 6 на 8.
610 = 01102
810 = 10002
0110
1000
1110
var a = 6, b = 8; console.log(a ^ b); // 14
Битовые сдвиги
При выполнении этого типа логических операций биты числа сдвигаются либо вправо (>>), либо влево ( > 2. 4010 = 1010002. После сдвига на 2 позиции вправо получим 10102 = 1010
40 >> 2 // = 10
Вот и всё, что я хотел вам сегодня рассказать про логические и побитовые операторы. Не отчаивайтесь, если что-то кажется вам сложным или непонятным. Иногда понимание приходит со временем и некоторые вещи можно пока и не понимать. К тому же, вряд ли вам понадобятся те же побитовые операции при написании реальных скриптов.
Побитовые операторы
Побитовые операторы интерпретируют операнды как последовательность из 32 битов (нулей и единиц). Они производят операции, используя двоичное представление числа, и возвращают новую последовательность из 32 бит (число) в качестве результата.
Эта глава требует дополнительных знаний в программировании и не очень важная, при первом чтении вы можете пропустить её и вернуться потом, когда захотите понять, как побитовые операторы работают.
Формат 32-битного целого числа со знаком
Побитовые операторы в JavaScript работают с 32-битными целыми числами в их двоичном представлении.
Это представление называется «32-битное целое со знаком, старшим битом слева и дополнением до двойки».
Разберём, как устроены числа внутри подробнее, это необходимо знать для битовых операций с ними.
Что такое двоичная система счисления, вам, надеюсь, уже известно. При разборе побитовых операций мы будем обсуждать именно двоичное представление чисел, из 32 бит.
Старший бит слева – это научное название для самого обычного порядка записи цифр (от большего разряда к меньшему). При этом, если больший разряд отсутствует, то соответствующий бит равен нулю.
Примеры представления чисел в двоичной системе:
Обратите внимание, каждое число состоит ровно из 32-битов.
Дополнение до двойки – это название способа поддержки отрицательных чисел.
Двоичный вид числа, обратного данному (например, 5 и -5 ) получается путём обращения всех битов с прибавлением 1.
То есть, нули заменяются на единицы, единицы – на нули и к числу прибавляется 1 . Получается внутреннее представление того же числа, но со знаком минус.
Например, вот число 314 :
Чтобы получить -314 , первый шаг – обратить биты числа: заменить 0 на 1 , а 1 на 0 :
Второй шаг – к полученному двоичному числу прибавить единицу, обычным двоичным сложением: 11111111111111111111111011000101 + 1 = 11111111111111111111111011000110 .
Итак, мы получили:
Принцип дополнения до двойки делит все двоичные представления на два множества: если крайний-левый бит равен 0 – число положительное, если 1 – число отрицательное. Поэтому этот бит называется знаковым битом.
Список операторов
В следующей таблице перечислены все побитовые операторы. Далее операторы разобраны более подробно.
Побитовые операторы работают следующим образом:
- Операнды преобразуются в 32-битные целые числа, представленные последовательностью битов. Дробная часть, если она есть, отбрасывается.
- Для бинарных операторов – каждый бит в первом операнде рассматривается вместе с соответствующим битом второго операнда: первый бит с первым, второй со вторым и т.п. Оператор применяется к каждой паре бит, давая соответствующий бит результата.
- Получившаяся в результате последовательность бит интерпретируется как обычное число.
Посмотрим, как работают операторы, на примерах.
Для удобной работы с примерами в этой статье, если вы захотите протестировать что-то в консоли, пригодятся две функции.
- parseInt(«11000», 2) – переводит строку с двоичной записью числа в число.
- n.toString(2) – получает для числа n запись в 2-ной системе в виде строки.
Без них перевод в двоичную систему и обратно был бы куда менее удобен. Более подробно они разбираются в главе Числа.
& (Побитовое И)
Выполняет операцию И над каждой парой бит.
Результат a & b равен единице только когда оба бита a и b равны единице.
Таблица истинности для & :
| (Побитовое ИЛИ)
Выполняет операцию ИЛИ над каждой парой бит. Результат a | b равен 1, если хотя бы один бит из a,b равен 1.
Таблица истинности для | :
^ (Исключающее ИЛИ)
Выполняет операцию «Исключающее ИЛИ» над каждой парой бит.
a Исключающее ИЛИ b равно 1, если только a=1 или только b=1 , но не оба одновременно a=b=1 .
Таблица истинности для исключающего ИЛИ:
Как видно, оно даёт 1, если ЛИБО слева 1 , ЛИБО справа 1 , но не одновременно. Поэтому его и называют «исключающее ИЛИ».
Исключающее или можно использовать для шифрования, так как эта операция полностью обратима. Двойное применение исключающего ИЛИ с тем же аргументом даёт исходное число.
Иначе говоря, верна формула: a ^ b ^ b == a .
Пусть Вася хочет передать Пете секретную информацию data . Эта информация заранее превращена в число, например строка интерпретируется как последовательность кодов символов.
Вася и Петя заранее договариваются о числовом ключе шифрования key .
- Вася берёт двоичное представление data и делает операцию data ^ key . При необходимости data бьётся на части, равные по длине key , чтобы можно было провести побитовое ИЛИ ^ для каждой части. В JavaScript оператор ^ работает с 32-битными целыми числами, так что data нужно разбить на последовательность таких чисел.
- Результат data ^ key отправляется Пете, это шифровка.
Например, пусть в data очередное число равно 9 , а ключ key равен 1220461917 .
- Петя, получив очередное число шифровки 1220461908 , применяет к нему такую же операцию ^ key .
- Результатом будет исходное число data .
Конечно, такое шифрование поддаётся частотному анализу и другим методам дешифровки, поэтому современные алгоритмы используют операцию XOR ^ как одну из важных частей более сложной многоступенчатой схемы.
Производит операцию НЕ над каждым битом, заменяя его на обратный ему.
Таблица истинности для НЕ:
Из-за внутреннего представления отрицательных чисел получается так, что
сдвигает первый операнд на указанное число битов влево. Лишние биты отбрасываются, справа добавляются нулевые биты.
Например, 9 даст 36 :
Операция сдвинула и отбросила два левых нулевых бита и добавила справа два новых нулевых.
Битовый сдвиг обычно имеет тот же эффект, что и умножение на два N раз, например:
Конечно, следует иметь в виду, что побитовые операторы работают только с 32-битными числами, поэтому верхний порог такого «умножения» ограничен:
>> (Правый битовый сдвиг, переносящий знак)
Этот оператор сдвигает биты вправо, отбрасывая лишние. При этом слева добавляется копия крайнего-левого бита.
Знак числа (представленный крайним-левым битом) при этом не меняется, так как новый крайний-левый бит имеет то же значение, что и исходном числе.
Поэтому он назван «переносящим знак».
Например, 9 >> 2 даст 2 :
Операция >> 2 сдвинула вправо и отбросила два правых бита 01 и добавила слева две копии первого бита 00 .
Аналогично, -9 >> 2 даст -3 :
Здесь операция >> 2 сдвинула вправо и отбросила два правых бита 11 и добавила слева две копии первого бита 11 . , Знак числа сохранён, так как крайний-левый (знаковый) бит сохранил значение 1 .
Битовый сдвиг >> N обычно имеет тот же результат, что и целочисленное деление на два N раз:
>>> (Правый сдвиг с заполнением нулями)
Этот оператор сдвигает биты первого операнда вправо. Лишние биты справа отбрасываются. Слева добавляются нулевые биты.
Знаковый бит становится равным 0, поэтому результат всегда положителен.
Для неотрицательных чисел правый сдвиг с заполнением нулями >>> и правый сдвиг с переносом знака >> дадут одинаковый результат, т.к в обоих случаях слева добавятся нули.
Для отрицательных чисел – результат работы разный. Например, -9 >>> 2 даст 1073741821 , в отличие от -9 >> 2 (даёт -3 ):
Применение побитовых операторов
Побитовые операторы используются редко, но всё же используются.
Случаи применения побитовых операторов, которые мы здесь разберём, составляют большинство всех использований в JavaScript.
В JavaScript побитовые операторы ^ , & , | выполняются после сравнений == .
Например, в сравнении a == b^0 будет сначала выполнено сравнение a == b , а потом уже операция ^0 , как будто стоят скобки (a == b)^0 .
Обычно это не то, чего мы хотим. Чтобы гарантировать желаемый порядок, нужно ставить скобки: a == (b^0) .
Маска
Для этого примера представим, что наш скрипт работает с пользователями.
У них могут быть различные роли в проекте:
Каждой роли соответствует ряд доступов к статьям и функциональности сайта.
Например, Гость может лишь просматривать статьи сайта, а Редактор – ещё и редактировать их, и тому подобное.
Что-то в таком духе:
Если вместо «Да» поставить 1 , а вместо «Нет» – 0 , то каждый набор доступов описывается числом:
В последней колонке находится десятичное число, которое получится, если прочитать строку доступов в двоичном виде.
Например, доступ гостя 10100 = 20 .
Такая интерпретация доступов позволяет «упаковать» много информации в одно число. Это экономит память, а кроме этого – это удобно, поскольку в дополнение к экономии – по такому значению очень легко проверить, имеет ли посетитель заданную комбинацию доступов!
Для этого посмотрим, как в 2-ной системе представляется каждый доступ в отдельности.
- Доступ, соответствующий только управлению правами: 00001 (=1) (все нули кроме 1 на позиции, соответствующей этому доступу).
- Доступ, соответствующий только изменению товаров: 00010 (=2) .
- Доступ, соответствующий только просмотру товаров: 00100 (=4) .
- Доступ, соответствующий только изменению статей: 01000 (=8) .
- Доступ, соответствующий только просмотру статей: 10000 (=16) .
Доступ одновременно на просмотр и изменение статей – это двоичное число с 1 на соответствующих позициях, то есть access = 11000 .
Как правило, доступы задаются в виде констант:
Из этих констант получить нужную комбинацию доступов можно при помощи операции | .
Теперь, чтобы понять, есть ли в доступе editor нужный доступ, например управление правами – достаточно применить к нему побитовый оператор И ( & ) с соответствующей константой.
Ненулевой результат будет означать, что доступ есть:
Такая проверка работает, потому что оператор И ставит 1 на те позиции результата, на которых в обоих операндах стоит 1 .
Можно проверить один из нескольких доступов.
Например, проверим, есть ли права на просмотр ИЛИ изменение товаров. Соответствующие права задаются битом 1 на втором и третьем месте с конца, что даёт число 00110 (= 6 в 10-ной системе).
Битовой маской называют как раз комбинацию двоичных значений ( check в примере выше), которая используется для проверки и выборки единиц на нужных позициях.
Маски могут быть весьма удобны.
В частности, их используют в функциях, чтобы одним параметром передать несколько «флагов», т.е. однобитных значений.
Пример вызова функции с маской:
Это довольно-таки коротко и элегантно, но, вместе с тем, применение масок налагает определённые ограничения. В частности, побитовые операторы в JavaScript работают только с 32-битными числами, а значит, к примеру, 33 доступа уже в число не упакуешь. Да и работа с двоичной системой счисления – как ни крути, менее удобна, чем с десятичной или с обычными логическими значениями true/false .
Поэтому основная сфера применения масок – это быстрые вычисления, экономия памяти, низкоуровневые операции, связанные с рисованием из JavaScript (3d-графика), интеграция с некоторыми функциями ОС (для серверного JavaScript), и другие ситуации, когда уже существуют функции, требующие битовую маску.
Округление
Так как битовые операции отбрасывают десятичную часть, то их можно использовать для округления. Достаточно взять любую операцию, которая не меняет значение числа.
JavaScript — Условные и логические операторы
В этой статье рассмотрим условные и логические операторы языка JavaScript.
Условные операторы JavaScript
Условные операторы — это операторы языка JavaScript (ECMAScript), которые в зависимости от некоторого условия позволяют выполнить одно или несколько определённых инструкций.
Формы условных операторов в JavaScript:
- условный оператор if (с одной ветвью);
- условный оператор if. else (с двумя ветвями);
- условный оператор else if. (с несколькими ветвями);
- тернарный оператор ( ?: );
- оператор выбора switch .
Условный оператор if
Синтаксис оператора if:
Условный оператор if состоит из:
- ключевого слова if ;
- условия (выражения в круглых скобках), которое должно равняться true или false (или быть приведено к одному из этих значений);
- инструкции, которую нужно выполнить , если условие является true или приведено к нему.
В этом примере в качестве условия используется значение true . Это означает, что инструкция count = 4 будет выполняться всегда. Данный пример просто приведен для пояснения принципа работы оператора if , т.к. он лишён всякого смысла.
Например , увеличим значение переменной votes на 1, если она (её тип) является числом:
Если необходимо выполнить несколько инструкций, то их необходимо поместить в фигурные скобки :
Рекомендуется, использовать фигурные скобки даже когда используется одна инструкция:
Оператор if. else
Оператор if. else используется, когда необходимо при истинности условия выполнить одни инструкции, а при ложности — другие.
Например , выведем в консоль сообщение о том, является ли число четным или нет:
Правило приведения условия к true или false
Если выражение в условии оператора if не равно true или false , то JavaScript приведёт его к одному из этих значений. Данное действие он выполняет с помощью так называемого «правила лжи».
Смысл данного правила: любое выражение является true, кроме следующих значений :
- false (ложь);
- «» или » (пустая строка);
- NaN (специальный числовой тип данных «не число»);
- 0 (число «ноль»);
- null («пустое» значение);
- undefined («неопределённое» значение).
Например , выведем в консоль браузера приветственное сообщение, в зависимости от того какое значение хранится в переменной nameUser :
Если переменная nameUser будет содержать пустую строку , то по правилу лжи, она будет приведена к значению false . Следовательно, в консоль будет выведено сообщение «Привет, гость!» .
А если, например, переменная nameUser будет содержать строку «Тимур» , то выражение в условии будет приведено к значению true . В результате, в консоли отобразится сообщение «Привет, Тимур!» .
Оператор else if. (несколько условий)
Условный (тернарный) оператор (?:)
Тернарный оператор – оператор JavaScript, который можно использовать, когда необходимо в зависимости от условия выполнить одно из двух заданных выражений.
Тернарный оператор состоит из трех операндов, которые разделяются с помощью символов ? и : . Условие тернарного оператора задаётся в первом операнде. Его также можно заключить в скобки. Если условие равно true или будет приведено к этому значению будет выполнено выражение1 , иначе — выражение 2 .
В JavaScript допустимы множественные тернарные операторы ( ?: ):
Вышеприведённый пример, но с использованием множественной записи оператора if. else :
Оператор switch
Оператор switch предназначен для выполнения одного варианта инструкций из нескольких в зависимости от значения выражения. Выбор того или иного варианта определяется посредством строгого равенства результата выражения значению случая ( case ).
Синтаксис оператора switch :
Ключевое слово default является необязательным. Оно используется, когда необходимо задать инструкции, которые нужно выполнить, если результат выражения будет не равен ни одному значению варианта ( case ).
Инструкция break является необязательной. Она предназначена для прерывания выполнения оператора switch и передачи управлению инструкции, идущей после него.
Например , выведем сообщение в консоль браузера о количестве конфет:
В вышеприведенном примере вычисленное выражение равно 3. Следовательно, будет выполнены инструкции message = ‘Две или три конфеты’ и break . Инструкция break прервёт дальнейшее выполнение оператора switch и передаст управление инструкции, идущей после него, т.е. console.log(message) . Она выведет в консоль сообщение «Две или три конфеты» .
Например , выведем выведем в консоль текущий день недели:
Пример, в котором не используется инструкция break :
В этом примере выражение оператора switch равно success . Следовательно, будет выполнена инструкция console.log(‘Успех!’) , которая выведет сообщение «Успех!» в консоль. Но так как после неё нет инструкции break , то выполнение скрипта будет продолжено в следующем варианте. Таким образом, инструкции будут выполняться до тех пока пока на пути не встретиться break или не будет достигнут конец оператора switch . В результате выполнения этого примера в консоль будут выведены 3 сообщения: «Успех!» , «Неверная капча!» и «Ошибка!» .
В некоторых случаях может требоваться именно такое поведение, но не в этом. Здесь просто допущена ошибка.
Исправленный вариант примера:
Логические операторы
В JavaScript различают следующие логические операторы:
Если в логическом выражении operand1 || operand2 используются булевы значения, то результатом этого выражения будет значение true , если хотя бы один из них равен true ; иначе значением этого выражения будет значение false .
Если в логическом выражении operand1 || operand2 используются не булевы значения, то результатом этого выражения будет operand1 , если его можно привести к true ; иначе результатом этого выражения будет operand2 .
Результатом логического выражения !operand1 будет значение true , если operand1 равно false или его можно привести к этому значению; иначе результатом этого выражения будет значение false .
Почему в JavaScript нет логического xor?
154 DarkLightA [2010-12-27 20:15:00]
Почему в JavaScript нет логического xor?
javascript logical-operators xor
12 ответов
JavaScript отслеживает свою родословную на C, а C не имеет логического оператора XOR. В основном потому, что это не полезно. Побитовое XOR чрезвычайно полезно, но за все годы программирования мне никогда не нужен логический XOR.
Если у вас есть две логические переменные, вы можете имитировать XOR с помощью:
С двумя произвольными переменными вы можете использовать ! , чтобы принудить их к логическим значениям, а затем использовать один и тот же трюк:
Это довольно неясно, хотя и, безусловно, заслуживает комментария. Действительно, вы могли бы даже использовать побитовый оператор XOR в этот момент, хотя это было бы слишком умно для моего вкуса:
66 Pikrass [2010-12-27 20:24:00]
Javascript имеет побитовый оператор XOR: ^
Вы можете использовать его с booleans, и он даст результат как 0 или 1 (который вы можете преобразовать обратно в boolean, например result = !!(op1 ^ op2) ). Но, как сказал Джон, это эквивалентно result = (op1 != op2) , что яснее.
27 Robert [2012-03-14 16:23:00]
В Javascript нет реальных логических логических операторов (хотя ! Подходит довольно близко). Логический оператор будет принимать только true или false качестве операндов и будет возвращать только true или false .
В Javascript && и || возьмите всевозможные операнды и верните всевозможные забавные результаты (что бы вы ни вводили в них).
Также логический оператор всегда должен учитывать значения обоих операндов.
В Javascript && и || возьмите ленивый ярлык и не оценивайте второй операнд в некоторых случаях и тем самым пренебрегайте его побочными эффектами. Такое поведение невозможно воссоздать с логическим xor.
a() && b() оценивает a() и возвращает результат, если он ложный. В противном случае он оценивает b() и возвращает результат. Следовательно, возвращаемый результат верен, если оба результата верны, и ложен в противном случае.
a() || b() a() || b() оценивает a() и возвращает результат, если он правдив. В противном случае он оценивает b() и возвращает результат. Следовательно, возвращаемый результат ложен, если оба результата ложны, и истинен в противном случае.
Итак, общая идея — сначала оценить левый операнд. Правильный операнд оценивается только при необходимости. И последнее значение — результат. Этот результат может быть чем угодно. Объекты, числа, строки. что угодно!
Это позволяет писать такие вещи, как
Но значение истинности этого результата также можно использовать для определения, вернул ли бы «реальный» логический оператор истину или ложь.
Это позволяет писать такие вещи, как
Но «логический» оператор xor ( ^^ ) всегда должен оценивать оба операнда. Это отличает его от других «логических» операторов, которые оценивают второй операнд только при необходимости. Я думаю, что именно поэтому в Javascript нет «логического» xor, чтобы избежать путаницы.
Так что же должно произойти, если оба операнда ложные? Оба могут быть возвращены. Но только один может быть возвращен. Который из? Первый? Или второй? Моя интуиция подсказывает мне вернуть первые, но обычно «логические» операторы, вычисляющие слева направо, и вернуть последнее оцененное значение. Или, может быть, массив, содержащий оба значения?
И если один операнд является правдивым, а другой — ложным, xor должен возвращать правдивый. Или, может быть, массив, содержащий истинный, чтобы сделать его совместимым с предыдущим случаем?
И, наконец, что должно произойти, если оба операнда истинны? Вы ожидаете что-то ложное. Но нет никаких ложных результатов. Так что операция не должна ничего возвращать. Так может быть undefined или.. пустой массив? Но пустой массив все еще правдив.
При использовании массива вы получите условия вроде if ((a ^^ b).length !== 1) < . Очень запутанно.
или легче читать:
потому что разработчики javascript считали, что это не нужно, поскольку это может быть выражено другими, уже реализованными логическими операторами.
вы могли бы просто иметь gon с nand, и это все, вы можете произвести впечатление на любую другую возможную логическую операцию.
Я лично считаю, что у него есть исторические причины, которые движутся с языков синтаксиса c-языка, где, насколько мне известно, xor отсутствует или, по крайней мере, необычно.
7 asiby [2013-08-05 21:14:00]
Да, просто выполните следующее. Предполагая, что вы имеете дело с логическими значениями A и B, тогда значение A XOR B можно вычислить в JavaScript, используя следующий
Предыдущая строка также эквивалентна следующему
Лично я предпочитаю xor1, так как мне приходится вводить меньше символов. Я считаю, что xor1 тоже быстрее. Он просто выполняет два вычисления. xor2 выполняет три вычисления.
Пояснение к Visual. Прочитайте таблицу ниже (где 0 означает false, а 1 означает true) и сравните 3-й и 5-й столбцы.