Оглавление
- Эквивалентность, введение и устранение
- Поведение
- Связь с естественным языком
- Связь с естественным языком[править | править код]
- Логические схемы «И» на транзисторах
- Битовая операция НЕ
- Битовые флаги
- Обозначения[править | править код]
- Датчики параметров
- Булева алгебра[править | править код]
- Характеристики
- Операторы сравнения PHP
- Компьютерные приложения
- Обозначения
- Арифметические операции
- Зачем нужны побитовые операторы?
- Формат 32-битного целого числа со знаком
- Использование логических операторов И/ИЛИ
- Логический оператор AND
- Побитовые И, ИЛИ, НЕ, исключающее ИЛИ
Эквивалентность, введение и устранение
Исключительная дизъюнкция , или J pq , может быть выражена в терминах конъюнкции («и логического», ), дизъюнкции («или логического», ) и логического отрицания ( ) следующим образом:
п⊕q{\ displaystyle p \ oplus q}∧{\ Displaystyle \ клин}∨{\ displaystyle \ lor}¬{\ Displaystyle \ lnot}
п⊕qзнак равно(п∨q)∧¬(п∧q){\ displaystyle {\ begin {matrix} p \ oplus q & = & (p \ lor q) \ land \ lnot (p \ land q) \ end {matrix}}}
Исключительную дизъюнкцию также можно сформулировать следующим образом:
п⊕q{\ displaystyle p \ oplus q}
- п⊕qзнак равно(п∧¬q)∨(¬п∧q){\ displaystyle {\ begin {matrix} p \ oplus q & = & (p \ land \ lnot q) \ lor (\ lnot p \ land q) \ end {matrix}}}
Такое представление XOR может быть полезно при построении схемы или сети, потому что оно имеет только одну операцию и небольшое количество операций и . Доказательство этой идентичности приведено ниже:
¬{\ Displaystyle \ lnot}∧{\ Displaystyle \ клин}∨{\ displaystyle \ lor}
- п⊕qзнак равно(п∧¬q)∨(¬п∧q)знак равно((п∧¬q)∨¬п)∧((п∧¬q)∨q)знак равно((п∨¬п)∧(¬q∨¬п))∧((п∨q)∧(¬q∨q))знак равно(¬п∨¬q)∧(п∨q)знак равно¬(п∧q)∧(п∨q){\ displaystyle {\ begin {matrix} p \ oplus q & = & (p \ land \ lnot q) & \ lor & (\ lnot p \ land q) \\ & = & ((p \ land \ lnot q) \ lor \ lnot p) & \ land & ((p \ land \ lnot q) \ lor q) \\ & = & ((p \ lor \ lnot p) \ land (\ lnot q \ lor \ lnot p)) & \ land & ((p \ lor q) \ land (\ lnot q \ lor q)) \\ & = & (\ lnot p \ lor \ lnot q) & \ land & (p \ lor q) \\ & = & \ lnot (p \ land q) & \ land & (p \ lor q) \ end {matrix}}}Иногда полезно отметить следующее:п⊕q{\ displaystyle p \ oplus q}
- п⊕qзнак равно¬((п∧q)∨(¬п∧¬q)){\ displaystyle {\ begin {matrix} p \ oplus q & = & \ lnot ((p \ land q) \ lor (\ lnot p \ land \ lnot q)) \ end {matrix}}}
или же:
- п⊕qзнак равно(п∨q)∧(¬п∨¬q){\ displaystyle {\ begin {matrix} p \ oplus q & = & (p \ lor q) \ land (\ lnot p \ lor \ lnot q) \ end {matrix}}}
Эту эквивалентность можно установить , дважды применяя законы Де Моргана к четвертой строке приведенного выше доказательства.
Исключающее или также эквивалентно отрицанию логической эквивалентности по правилам материальной импликации.
Таким образом, мы имеем:
- п⊕qзнак равно(п∧¬q)∨(¬п∧q)знак равнопq¯+п¯qзнак равно(п∨q)∧(¬п∨¬q)знак равно(п+q)(п¯+q¯)знак равно(п∨q)∧¬(п∧q)знак равно(п+q)(пq¯){\ displaystyle {\ begin {matrix} p \ oplus q & = & (p \ land \ lnot q) & \ lor & (\ lnot p \ land q) & = & p {\ overline {q}} + {\ overline {p}} q \\ & = & (p \ lor q) & \ land & (\ lnot p \ lor \ lnot q) & = & (p + q) ({\ overline {p}} + {\ overline {q}}) \\ & = & (p \ lor q) & \ land & \ lnot (p \ land q) & = & (p + q) ({\ overline {pq} }) \ end {matrix}}}
Поведение
Элементы Исключающее ИЛИ, Исключающее ИЛИ-НЕ, Нечётность и Чётность вычисляют соответствующую функцию от значений на входах и выдают результат на выход.
По умолчанию, неподключенные входы игнорируются — то есть, если входы действительно не имеют ничего подключенного к ним — даже провода. Таким образом, вы можете добавить 5-входовый элемент, но подключить только два входа, и он будет работать как 2-входовый элемент; это избавляет вас от необходимости беспокоиться о настройке количества входов каждый раз при создании элемента. (Если все входы не подключены, то на выходе значение ошибки X.) Некоторые пользователи, однако, предпочитают, чтобы Logisim настаивал, чтобы все входы были подключены, поскольку это соответствует реальным элементам. Вы можете включить это поведение, выбрав меню Проект > Параметры…, перейдя на вкладку Моделирование, и выбрав вариант Ошибка для неопределённых входов
для Выход элемента при неопределённости
.
Двухвходовая таблица истинности для элементов следующая.
x | y | Исключающее ИЛИ | Исключающее ИЛИ-НЕ | Нечётность | Чётность |
---|---|---|---|---|---|
1 | 1 | ||||
1 | 1 | 1 | |||
1 | 1 | 1 | |||
1 | 1 | 1 | 1 |
Как вы можете видеть, элементы Нечётность и Исключающее ИЛИ ведут себя одинаково в случае двух входов; аналогично, элементы Чётность и Исключающее ИЛИ-НЕ ведут себя одинаково. Но если входов с определённым значением больше двух, то элемент Исключающее ИЛИ будет давать на выходе 1, когда единица строго на одном входе, тогда как элемент Нечётность даст на выходе 1, когда единица на нечётном количестве входов. Элемент Исключающее ИЛИ-НЕ будет давать на выходе 1, когда входов с единицей строго не один, тогда как элемент Чётность даст 1, когда входов с единицей чётное количество. Элементы Исключающее ИЛИ и Исключающее ИЛИ-НЕ имеют атрибут, названный Многовходовое поведение, который позволяет настроить их на использование поведения элементов Нечётность и Чётность.
Если на каких-либо входах значение ошибки (например, если противоречивые значения поступают на один и тот же провод) или плавающее значение, то на выходе будет значение ошибки.
Многобитные версии каждого элемента будут выполнять свои однобитные преобразования над входами поразрядно.
Примечание: многие специалисты утверждают, что поведение фигурного элемента Исключающее ИЛИ должно соответствовать поведению элемента Нечётность, но по этому вопросу нет согласия. Поведение Logisim по умолчанию для элемента Исключающее ИЛИ основано на стандарте IEEE 91. Это также согласуется с интуитивным пониманием термина Исключающее ИЛИ: официант, спрашивающий, хотите вы гарнир из картофельного пюре, моркови, зеленого горошка, или шинкованной капусты, примет только один выбор, а не три, независимо от того, что вам могут сказать некоторые специалисты. (Должен признать, однако, что я не подвергал это заявление серьезным испытаниям.) Вы можете настроить элементы Исключающее ИЛИ и Исключающее ИЛИ-НЕ на использование одного из вариантов, меняя его атрибут Многовходовое поведение
.
Связь с естественным языком
В естественном языке операция «сложение по модулю» эквивалентна двум выражениям:
- «результат истинен (равен 1), если A не равно B (A≠B)»;
- «если A не равно B (A≠B), то истина (1)».
Часто указывают на сходство между сложением по модулю 2 и конструкцией «либо … либо …» в естественном языке. Составное утверждение «либо A, либо B» считается истинным, когда истинно либо A, либо B, но не оба сразу; в противном случае составное утверждение ложно. Это в точности соответствует определению операции в булевой алгебре, если «истину» обозначать как 1{\displaystyle 1}, а «ложь» как {\displaystyle 0}.
Эту операцию нередко сравнивают с дизъюнкцией потому, что они очень похожи по свойствам, и обе имеют сходство с союзом «или» в повседневной речи. Сравните правила для этих операций:
- A∨B{\displaystyle A\lor B} истинно, если истинно A{\displaystyle A} или B{\displaystyle B}, или оба сразу («хотя бы один из двух»).
- A⊕B{\displaystyle A\oplus B} истинно, если истинно A{\displaystyle A} или B{\displaystyle B}, но не оба сразу («только один из двух»).
Операция ⊕{\displaystyle \oplus }исключает последний вариант («оба сразу») и по этой причине называется исключающим «ИЛИ».
Операция ∨{\displaystyle \lor }включает последний вариант («оба сразу») и по этой причине иногда называется включающим «ИЛИ».
Неоднозначность естественного языка заключается в том, что союз «или» может применяться в обоих случаях.
Связь с естественным языком[править | править код]
В естественном языке операция «сложение по модулю» эквивалентна двум выражениям:
- «результат истинен (равен 1), если A не равно B (A≠B)»;
- «если A не равно B (A≠B), то истина (1)».
Часто указывают на сходство между сложением по модулю 2 и конструкцией «либо … либо …» в естественном языке. Составное утверждение «либо A, либо B» считается истинным, когда истинно либо A, либо B, но не оба сразу; в противном случае составное утверждение ложно. Это в точности соответствует определению операции в булевой алгебре, если «истину» обозначать как 1{\displaystyle 1}, а «ложь» как {\displaystyle 0}.
Эту операцию нередко сравнивают с дизъюнкцией потому, что они очень похожи по свойствам, и обе имеют сходство с союзом «или» в повседневной речи. Сравните правила для этих операций:
- A∨B{\displaystyle A\lor B} истинно, если истинно A{\displaystyle A} или B{\displaystyle B}, или оба сразу («хотя бы один из двух»).
- A⊕B{\displaystyle A\oplus B} истинно, если истинно A{\displaystyle A} или B{\displaystyle B}, но не оба сразу («только один из двух»).
Операция ⊕{\displaystyle \oplus }исключает последний вариант («оба сразу») и по этой причине называется исключающим «ИЛИ». Операция ∨{\displaystyle \lor }включает последний вариант («оба сразу») и по этой причине иногда называется включающим «ИЛИ». Неоднозначность естественного языка заключается в том, что союз «или» может применяться в обоих случаях.
Логические схемы «И» на транзисторах
Логические схемы И могут быть собраны на транзисторах (рис. 3). В схеме И для положительной логики используются транзисторы типа n — p — n (рис. 3, а). При наличии сигнала 0 на одном из входов соответствующий транзистор закрыт напряжением смещения Есм, так как напряжение сигнала 0 ниже Есм. Второй транзистор может быть открыт при сигнале на входе 1 (напряжение сигнала 1 выше Есм). Переход эмиттер — коллектор закрытого транзистора практически обрывает цепь питания, и на выходе возникает сигнал 0.
Рис. 3. Схема И на транзисторах
Когда на входах появляются сигналы 1, оба транзистора открыты и на выходе возникает сигнал 1. В схеме И для отрицательной логики (рис. 3, б) используются транзисторы типа р — n — р. Принципы работы данной и предыдущей схем аналогичны, однако полярность сигналов, смещения и питания обратная.
Битовая операция НЕ
Начнем с самой
простой битовой операции НЕ, которая выполняет инверсию бит в соответствии с
такой табличкой:
x |
НЕ |
1 |
|
1 |
На языке Java она
записывается как ~ тильда. И приведем такую программу.
int var = 121; //двоичный вид: 00000000 00000000 00000000 01111001 int not_v = ~var; //результат: 11111111 11111111 11111111 10000110 (число -122) System.out.println(not_v);
Здесь мы сначала
задаем переменную var со значением 121, затем, выполняем ее
побитовую инверсию, и выводим результат на экран.
Запустим
программу и видим на экране число -122, что и должно быть, так как инверсия
последних 7 бит дает
1111001 = 121+1
значит, это
число -122.
Битовые флаги
Расммотрим синтетический пример. Пусть у нас есть три логические переменные, и нам нужно вывести определённое значение
в зависимости от всех этих переменных сразу. Очевидно, что может быть 23 возможных вариантов. Запишем
это условие в виде ветвления:
#include <stdio.h> int main() { unsigned char a, b, c; a = 1; b = 0; c = 0; if (a) { if (b) { if (c) { printf("true true true"); } else { printf("true true false"); } } else { if (c) { printf("true false true"); } else { printf("true false false"); } } } else { if (b) { if (c) { printf("false true true"); } else { printf("false true false"); } } else { if (c) { printf("false false true"); } else { printf("false false false"); } } } _getch(); return 0; }
Мы получили 8 ветвей. Пусть теперь нам понадобилось добавить ещё одно условие. Тогда число ветвей удвоится, и программа
станет ещё сложней для понимания и отладки. Перепишем пример.
Если каждое из наших логичесих значений сдвинуть на своё число бит влево и логически сложить, то мы получим свою уникальную
комбинацию бит в зависимоти от значений a, b и c:
#include <stdio.h> #include <limits.h> void printbits (int n) { int i; for (i = CHAR_BIT - 1; i >= 0; i--) { printf("%d", (n & (1 << i)) != 0); } printf("\n"); } int main() { unsigned char a, b, c; unsigned char res; a = 1; b = 0; c = 0; res = c | b << 1 | a << 2; printbits(res); a = 0; b = 1; c = 1; res = c | b << 1 | a << 2; printbits(res); a = 1; b = 0; c = 1; res = c | b << 1 | a << 2; printbits(res); _getch(); return 0; }
Используем этот подход к нашей задаче и заменим ветвеление на switch:
#include <stdio.h> int main() { unsigned char a, b, c; unsigned char res; a = 1; b = 0; c = 0; res = c | b<< 1 | a << 2; switch (res) { case 0b00000000: printf("false false false"); break; case 0b00000001: printf("false false true"); break; case 0b00000010: printf("false true false"); break; case 0b00000011: printf("false true true"); break; case 0b00000100: printf("true false false"); break; case 0b00000101: printf("true false true"); break; case 0b00000110: printf("true true false"); break; case 0b00000111: printf("true true true"); break; } _getch(); return 0; }
Этот метод очень часто используется для назначения опций функций в разных языках программирования. Каждый
флаг принимает своё уникальное название, а их совместное значение как логическая сумма всех используемых флагов.
Например, библиотека fcntl:
char *fp = "/home/ec2-user/file.txt"; int flag = O_RDWR | O_CREAT | O_TRUNC | O_APPEND; int fd = open(fp, flag, 0644);
Q&A
Всё ещё не понятно? – пиши вопросы на ящик
Обозначения[править | править код]
Запись может быть префиксной («польская запись») — знак операции ставится перед операндами, инфиксной — знак операции ставится между операндами и постфиксной — знак операции ставится после операндов. При числе операндов более 2 префиксная и постфиксная записи экономичнее инфиксной записи. Чаще всего встречаются следующие варианты записи:⊕2(a,b), a{\displaystyle \oplus _{2}(a,b),~a} ^ b, a⊕b,a⊕2b,a+2b,{\displaystyle b,~a\oplus b,a\oplus _{2}b,a+_{2}b,} a ≠ b, a≠b,(a,b)⊕2,a XOR b{\displaystyle a\neq b,(a,b)\oplus _{2},a~XOR~b}
В Юникоде есть символы для сложения по модулю 2: U+22BB ⊻ xor, U+2295 ⊕ circled plus и U+2A27 ⨧ plus sign with subscript two, U+2A52 ⩒ logical or with dot above, а также символ для суммы по модулю 2: U+2A0A ⨊ modulo two sum.
Датчики параметров
Датчики параметров служат для преобразования контролируемых параметров в преобразовательных устройствах (обычно тока и напряжения) в выходное напряжение. В большинстве случаев информация о напряжении и токе требуется в виде постоянного напряжения, для чего в датчике устанавливается выпрямитель и емкостный фильтр.
Датчики тока и напряжения (рис. 10) в трехфазной сети используют соответственно трансформаторы тока и напряжения. Трансформаторы тока устанавливаются во все три фазы и соединяются звездой (вторичные обмотки), переменное напряжение подается на выпрямитель, собранный по схеме Ларионова, а затем на делитель напряжения, состоящий из двух резисторов.
Рис. 10. Датчики параметров
На одном из устанавливается емкостный фильтр, и с него снимается напряжение пропорциональное среднему значению тока. В датчике напряжения используется трехфазный трансформатор напряжения, и выходное напряжение пропорционально среднему действующему значению переменного напряжения. К1 и К2 — коэффициенты пропорциональности.
Выходное устройство предназначено для окончательного формирования и усиления импульсов управления. В качестве ключа в схемах выходных устройств могут применяться транзисторы или тиристоры. В схемах используются элементы, позволяющие формировать импульсы специальной формы, обеспечивающие форсировку включения тиристора.
На рис. 11 показан транзисторный вариант такой схемы. Конденсатор С в промежутках между подачей входных импульсов Uвх заряжается напряжением питания Ек. При подаче входного импульса между эмиттером и базой транзистора Т, если его значение больше напряжения смещения Еб, транзистор открывается и конденсатор С разряжается на первичную обмотку трансформатора. Скорость разряда конденсатора обеспечивает уменьшение тока в первичной обмотке трансформатора и максимальное значение вторичной э.д.с. и выходного напряжения Uвых.
Рис. 11. Схема для формирования импульсов специальной формы
После разряда конденсатора ток первичной обмотки ограничивается сопротивлением резистора R1. Диод Д1 шунтирует входную цепь транзистора при подаче Uвх обратного знака. При снятии входного импульса транзистор закрывается напряжением смещения Еб.
Прямого падения напряжения на диоде Д1 от напряжения смещения достаточно доя запирания транзистора Т. Резистор R2 ограничивает базовый ток. Диод Д2 в цепи вторичной обмотки трансформатора создает разрядный контур для вторичной э. д. с. обратной полярности.
Булева алгебра[править | править код]
В булевой алгебре сложение по модулю 2 — это функция двух, трёх и более переменных (они же — операнды операции, они же — аргументы функции). Переменные могут принимать значения из множества {,1}{\displaystyle \{0,1\}}. Результат также принадлежит множеству {,1}{\displaystyle \{0,1\}}. Вычисление результата производится по простому правилу, либо по таблице истинности. Вместо значений ,1{\displaystyle 0,1} может использоваться любая другая пара подходящих символов, например false,true{\displaystyle false,true} или F,T{\displaystyle F,T} или «ложь», «истина», но при этом необходимо доопределять старшинство, например, true>false{\displaystyle true>false}.
Таблицы истинности:
для бинарного сложения по модулю 2 (применяется в двоичных полусумматорах):55–61:
a{\displaystyle a} | b{\displaystyle b} | a⊕b{\displaystyle a\oplus b} |
---|---|---|
1 | 1 | |
1 | 1 | |
1 | 1 |
Правило: результат равен {\displaystyle 0}, если оба операнда равны; во всех остальных случаях результат равен 1{\displaystyle 1}.
для тернарного сложения по модулю 2 (применяется в двоичных полных сумматорах):
a{\displaystyle a} | b{\displaystyle b} | c{\displaystyle c} | a⊕b⊕c{\displaystyle a\oplus b\oplus c} |
---|---|---|---|
1 | 1 | ||
1 | 1 | ||
1 | 1 | ||
1 | 1 | ||
1 | 1 | ||
1 | 1 | ||
1 | 1 | 1 | 1 |
Правило: результат равен {\displaystyle 0}, если нет операндов, равных 1{\displaystyle 1}, либо их чётное количество.
Характеристики
- Коммутативность : да
-
А⊕B{\ displaystyle A \ oplus B} ⇔{\ displaystyle \ Leftrightarrow} B⊕А{\ displaystyle B \ oplus A} ⇔{\ displaystyle \ Leftrightarrow} - Ассоциативность : да
-
А{\ displaystyle ~ A} ⊕ {\ displaystyle ~~~ \ oplus ~~~} (B⊕C){\ displaystyle (B \ oplus C)} ⇔{\ displaystyle \ Leftrightarrow} (А⊕B){\ displaystyle (A \ oplus B)} ⊕ {\ displaystyle ~~~ \ oplus ~~~} C{\ displaystyle ~ C} ⊕ {\ displaystyle ~~~ \ oplus ~~~} ⇔{\ displaystyle \ Leftrightarrow} ⇔{\ displaystyle \ Leftrightarrow} ⊕ {\ displaystyle ~~~ \ oplus ~~~} - Распределительность :
- Исключающее или не распределяется по какой-либо двоичной функции (даже самой), а . (Соединение и исключающее или образуют операции умножения и сложения поля GF (2) , и, как и в любом другом поле, они подчиняются закону распределения.)C∧(А⊕B)знак равно(C∧А)⊕(C∧B){\ Displaystyle С \ земля (A \ oplus B) = (C \ земля A) \ oplus (C \ земля B)}
- Идемпотентность : нет
-
А {\ displaystyle ~ A ~} ⊕ {\ displaystyle ~ \ oplus ~} А {\ displaystyle ~ A ~} ⇔{\ displaystyle \ Leftrightarrow} {\ displaystyle ~ 0 ~} ⇎{\ displaystyle \ nLeftrightarrow} А {\ displaystyle ~ A ~} ⊕ {\ displaystyle ~ \ oplus ~} ⇔{\ displaystyle \ Leftrightarrow} ⇎{\ displaystyle \ nLeftrightarrow} - Монотонность : нет
-
А→B{\ displaystyle A \ rightarrow B} ⇏{\ displaystyle \ nRightarrow} (А⊕C){\ displaystyle (A \ oplus C)} →{\ displaystyle \ rightarrow} (B⊕C){\ displaystyle (B \ oplus C)} ⇏{\ displaystyle \ nRightarrow} ⇔{\ displaystyle \ Leftrightarrow} →{\ displaystyle \ rightarrow} - Сохранение правды: нет
- Когда все входные данные верны, выход неверен.
А∧B{\ displaystyle A \ land B} ⇏{\ displaystyle \ nRightarrow} А⊕B{\ displaystyle A \ oplus B} ⇏{\ displaystyle \ nRightarrow} - Сохранение лжи: да
- Когда все входы ложны, выход ложен.
А⊕B{\ displaystyle A \ oplus B} ⇒{\ displaystyle \ Rightarrow} А∨B{\ Displaystyle A \ lor B} ⇒{\ displaystyle \ Rightarrow} - Спектр Уолша : (2,0,0, −2)
- Non- : 0
- Функция линейная.
Если для истинного (1) и ложного (0) используются двоичные значения, то исключающее или работает точно так же, как сложение по модулю 2.
Операторы сравнения PHP
Операторы сравнения предоставляют возможность сравнивать одно значение с другим и возвращать истинный или ложный результат в зависимости от статуса совпадения. Например, вы можете использовать оператор сравнения, чтобы проверить, соответствует ли значение переменной определенному числу или идентична ли одна строка другой. PHP предоставляет широкий выбор операторов сравнения практически для любых задач сравнения.
Операторы сравнения используются с двумя операндами, один слева и один справа от оператора. В следующей таблице представлены операторы сравнения PHP и приведены краткие описания и примеры:
Оператор | название | Синтаксис | Операция |
---|---|---|---|
== | Равно | $x == $y | Возвращает True, если оба операнда равны |
!= | Не равно | $x != $y | Возвращает True, если оба операнда не равны |
<> | Не равно | $x <> $y | Возвращает True, если оба операнда не равны |
=== | Тождественно равно | $x === $y | Возвращает True, если оба операнда равны и относятся к одному типу. |
!== | Тождественно не равно | $x == $y | Возвращает True, если оба операнда не равны и относятся к разным типам. |
< | Меньше | $x < $y | Возвращает True, если $x меньше $y |
> | Больше | $x > $y | Возвращает True, если $x больше $y |
<= | Меньше или равно | $x <= $y | Возвращает True, если $x меньше или равно $y |
>= | Больше или равно | $x >= $y | Возвращает True, если $x больше или равно $y |
<=> | Космический корабль | $x <=> $y | Возвращает целое число, меньшее, равное или большее нуля, в зависимости от того, меньше ли $ x, равно или больше $ y. Представлено в PHP 7. |
Примечание: При попытке вывести результат операции сравнения операндов на экран, значение отобразится в окне браузера как 1. Значение соответствует числу и не отображается на экран. Чтобы вывести на экран результат в виде или используйте функцию .
При сравнивании целого числа со строкой, строка будет преобразована к числу. В случае, если вы сравниваете две числовые строки, они сравниваются как целые числа:
Оператор spaceship (космический корабль)
Этот оператор предназначен для сравнения двух выражений. Он возвращает -1, 0 или 1 если $a, соответственно, меньше, равно или больше чем $b. Правила, используемые комбинированным оператором сравнения, такие же, как и используемые в настоящее время операторами сравнения PHP: . Сравнение производится в соответствии с правилами сравнения типов PHP.
Компьютерные приложения
Помимо использования, связанного с криптографией, функция исключающего ИЛИ позволяет быстро сбросить значение переменной (часто регистра ) до нуля.
Возьмем, например, ассемблерный код, который использует исключающее ИЛИ для сброса значения регистра eax до нуля:
xor eax, eax
На процессорах типа x86 эта инструкция короче (по количеству байтов), чем следующий интуитивно понятный код:
mov eax,
Он также позволяет обнулить переменную, когда условия не позволяют использовать байт 0x00 в двоичном коде ( шеллкоде ).
Вы также можете использовать исключающее ИЛИ для обмена двумя переменными без использования временной переменной .
Обозначения
Запись может быть префиксной («польская запись») — знак операции ставится перед операндами, инфиксной — знак операции ставится между операндами и постфиксной — знак операции ставится после операндов. При числе операндов более 2 префиксная и постфиксная записи экономичнее инфиксной записи. Чаще всего встречаются следующие варианты записи:⊕2(a,b), a{\displaystyle \oplus _{2}(a,b),~a} ^ b, a⊕b,a⊕2b,a+2b,{\displaystyle b,~a\oplus b,a\oplus _{2}b,a+_{2}b,} a ≠ b, a≠b,(a,b)⊕2,a XOR b{\displaystyle a\neq b,(a,b)\oplus _{2},a~XOR~b}
В Юникоде есть символы для сложения по модулю 2: U+22BB ⊻ xor, U+2295 ⊕ circled plus и U+2A27 ⨧ plus sign with subscript two, U+2A52 ⩒ logical or with dot above, а также символ для суммы по модулю 2: U+2A0A ⨊ modulo two sum.
Арифметические операции
Основные бинарные операции, расположенные в порядке уменьшения приоритета:
- * — умножение;
- — деление;
- + — сложение;
- — — вычитание;
- % — остаток от целочисленного деления.
Основные унарные операции:
- ++ — инкрементирование (увеличение на 1);
- –– — декрементирование (уменьшение на 1);
- — — изменение знака.
Результат вычисления выражения, содержащего операции инкрементирования или декрементирования, зависит от того, где расположен знак операции (до объекта или после него). Если операция расположена до объекта, то сначала происходит изменение значения переменной на 1, а потом это значение используется для выполнения следующих операций. Если операция ++ или — расположена после переменной, то сначала выполняется операция, а потом значение переменной изменяется на 1.Пример:
123456 int a=2;int b=3;int c;c = a*++b;// c=8, поскольку в операции умножения//уже b=4 |
123456 int a=2;int b=3;int d;d = a*b++;// d=6, поскольку в операции умножения b=3,// следующим действием будет b=4 |
Бинарные арифметические операции могут быть объединены с операцией присваивания:
- объект *= выражение; // объект = объект * выражение
- объект /= выражение; // объект = объект / выражение
- объект += выражение; // объект = объект + выражение
- объект -= выражение; // объект = объект — выражение
- объект %= выражение; // объект = объект % выражение
Зачем нужны побитовые операторы?
В далеком прошлом компьютерной памяти было очень мало и ею сильно дорожили. Это было стимулом максимально разумно использовать каждый доступный бит. Например, в логическом типе данных bool есть всего лишь два возможных значения (true и false), которые могут быть представлены одним битом, но по факту занимают целый байт памяти! А это, в свою очередь, из-за того, что переменные используют уникальные адреса памяти, а они выделяются только в байтах. Переменная bool занимает 1 бит, а другие 7 бит — тратятся впустую.
Используя побитовые операторы, можно создавать функции, которые позволят уместить 8 значений типа bool в переменную размером 1 байт, что значительно сэкономит потребление памяти. В прошлом такой трюк был очень популярен. Но сегодня, по крайней мере, в прикладном программировании, это не так.
Теперь памяти стало существенно больше и программисты обнаружили, что лучше писать код так, чтобы было проще и понятнее его поддерживать, нежели усложнять его ради незначительной экономии памяти. Поэтому спрос на использование побитовых операторов несколько уменьшился, за исключением случаев, когда необходима уж максимальная оптимизация (например, научные программы, которые используют огромное количество данных; игры, где манипуляции с битами могут быть использованы для дополнительной скорости; встроенные программы, где память по-прежнему ограничена).
В языке С++ есть 6 побитовых операторов:
Оператор | Символ | Пример | Операция |
Побитовый сдвиг влево | << | x << y | Все биты в x смещаются влево на y бит |
Побитовый сдвиг вправо | >> | x >> y | Все биты в x смещаются вправо на y бит |
Побитовое НЕ | ~ | ~x | Все биты в x меняются на противоположные |
Побитовое И | & | x & y | Каждый бит в x И каждый соответствующий ему бит в y |
Побитовое ИЛИ | | | x | y | Каждый бит в x ИЛИ каждый соответствующий ему бит в y |
Побитовое исключающее ИЛИ (XOR) | ^ | x ^ y | Каждый бит в x XOR с каждым соответствующим ему битом в y |
В побитовых операциях следует использовать только целочисленные типы данных unsigned, так как C++ не всегда гарантирует корректную работу побитовых операторов с целочисленными типами signed.
Правило: При работе с побитовыми операторами используйте целочисленные типы данных unsigned.
Формат 32-битного целого числа со знаком
Побитовые операторы в JavaScript работают с 32-битными целыми числами в их двоичном представлении.
Это представление называется «32-битное целое со знаком, старшим битом слева и дополнением до двойки».
Разберём, как устроены числа внутри подробнее, это необходимо знать для битовых операций с ними.
Что такое двоичная система счисления, вам, надеюсь, уже известно. При разборе побитовых операций мы будем обсуждать именно двоичное представление чисел, из 32 бит.
Старший бит слева – это научное название для самого обычного порядка записи цифр (от большего разряда к меньшему)
При этом, если больший разряд отсутствует, то соответствующий бит равен нулю.
Примеры представления чисел в двоичной системе:
Обратите внимание, каждое число состоит ровно из 32-битов.
Дополнение до двойки – это название способа поддержки отрицательных чисел.
Двоичный вид числа, обратного данному (например, и ) получается путём обращения всех битов с прибавлением 1.
То есть, нули заменяются на единицы, единицы – на нули и к числу прибавляется. Получается внутреннее представление того же числа, но со знаком минус.
Например, вот число :
Чтобы получить , первый шаг – обратить биты числа: заменить на , а на :
Второй шаг – к полученному двоичному числу прибавить единицу, обычным двоичным сложением: .
Итак, мы получили:
Принцип дополнения до двойки делит все двоичные представления на два множества: если крайний-левый бит равен – число положительное, если – число отрицательное
Поэтому этот бит называется знаковым битом.
Использование логических операторов И/ИЛИ
Иногда возникают ситуации, когда смешивания логических операторов И и ИЛИ в одном выражении не избежать. Тогда следует знать о возможных проблемах, которые могут произойти.
Многие программисты думают, что логические И и ИЛИ имеют одинаковый приоритет (или забывают, что это не так), так же как и сложение/вычитание или умножение/деление. Тем не менее, приоритет логического И выше приоритета ИЛИ. Таким образом, операции с оператором И всегда будут вычисляться первыми (если только операции с ИЛИ не находятся в круглых скобках).
Рассмотрим следующее выражение: . Поскольку приоритет логического И выше, то обрабатываться выражение будет так:
А не так:
Хорошей практикой является использование круглых скобок с операциями. Это предотвратит ошибки приоритета, увеличит читабельность кода и чётко даст понять компилятору, как следует обрабатывать выражения. Например, вместо того, чтобы писать , лучше записать .
Логический оператор AND
Синтаксис:Операнд_1 AND Операнд_2
Оператор AND выполняет логическую конъюнкцию.
Результатом данной операции является значение True, только когда оба операнда имеют значение True, иначе — False.
Таблица истинности
Операнд_1 | Операнд_2 | Результат |
True | True | True |
True | False | False |
False | True | False |
False | False | False |
Оператор AND можно использовать для нескольких операндов:
(5
Независимо от количества операндов результатом логической операции AND будет True только в том случае, когда все операнды выражения будут иметь значение True.
В любом другом случае результатом будет False
Обратите внимание, что операнды заключаются в круглые скобки
Побитовые И, ИЛИ, НЕ, исключающее ИЛИ
Напомню для начала, что логические операции И, ИЛИ, исключающее ИЛИ и НЕ могут быть описаны с помощью таблиц истинности
X | Y | X AND Y |
---|---|---|
1 | ||
1 | ||
1 | 1 | 1 |
X | Y | X OR Y |
---|---|---|
1 | 1 | |
1 | 1 | |
1 | 1 | 1 |
X | Y | X XOR Y |
---|---|---|
1 | 1 | |
1 | 1 | |
1 | 1 |
X | NOT X |
---|---|
1 | |
1 |
В побитовых (bit-wise) операциях значение бита, равное 1, рассматривается как логическая истина, а 0 как ложь. Побитовое И (оператор &) берёт два числа и логически умножает
соответствующие биты. Например, если логически умножить 3 на 8, то получим 0
char a = 3; char b = 8; char c = a & b; printf("%d", c);
Так как в двоичном виде 3 в виде однобайтного целого представляет собой
а 8
Первый бит переменной c равен логическому произведению первого бита числа a и первого бита числа b. И так для каждого бита.
Соответственно, побитовое произведение чисел 31 и 17 даст 17, так как 31 это
, а 17 это
Побитовое произведение чисел 35 и 15 равно 3.
Аналогично работает операция побитового ИЛИ (оператор |), за исключением того, что она логически суммирует соответствующие биты чисел без переноса.
Например,
char a = 15; char b = 11; char c = a | b; printf("%d", c);
выведет 15, так как 15 это , а 11 это 00001011
Побитовое ИЛИ для чисел 33 и 11 вернёт 43, так как 33 это , а 11 это
Побитовое отрицание (оператор ~) работает не для отдельного бита, а для всего числа целиком. Оператор инверсии меняет ложь на истину, а истину на ложь, для каждого бита.
Например,
char a = 65; char b = ~a; printf("%d", b);
Выведет -66, так как 65 это , а инверсия даст
что равно -66. Кстати, вот алгоритм для того, чтобы сделать число отрицательным: для нахождение дополнительного кода числа его надо инвертировать и
прибавить к нему единицу.
char a = 107; char b = ~a + 1; printf("a = %d, -a = %d", a, b);
Исключающее ИЛИ (оператор ^) применяет побитово операцию XOR. Например, для чисел
char a = 12; char b = 85; char c = a ^ b; printf("%d", c);
будет выведено 89, так как a равно , а b равно . В итоге получим
Иногда логические операторы && и || путают с операторами & и |. Такие ошибки могут существовать в коде достаточно долго,
потому что такой код в ряде случаев будет работать. Например, для чисел 1 и 0. Но так как в си истиной является любое ненулевое значение,
то побитовое умножение чисел 3 и 4 вернёт 0, хотя логическое умножение должно вернуть истину.
int a = 3; int b = 4; printf("a & b = %d\n", a & b); //выведет 0 printf("a && b = %d\n", a && b);//выведет не 0 (конкретнее, 1)