Как раскрывается исключающее или
Перейти к содержимому

Как раскрывается исключающее или

  • автор:

Калькулятор истинности: все о логике для программиста

В программировании и реальной жизни полно ситуаций, при которых нет никакой необходимости вникать в глубины решаемых задач. Все ясно при первом же рассмотрении темы. Но случается и так, что требуется подтвердить или опровергнуть выражение. Здесь в силу вступает так называемая логика высказываний.

Соответствующий момент играет важную роль не только в жизни, но и в науках. Пример – математика, программирование, психология. Можно использовать разнообразную логику высказываний для подтверждения и опровержения результатов. Обо всем этом будет рассказано далее.

Понятие логики

Логические утверждения – это не просто словосочетание. Логика является целой наукой. Ее изучение помогает правильно и здраво рассуждать. Благодаря этому, человек или устройство смогут делать грамотные выводы, опираясь на рассуждения.

При рассмотрении того или иного вопроса, человек будет на основе заключений логического характера строить гипотезы. В конце 19 века математики смогли перевести процесс осмысления в понятную форму – математическую. Такие логические «высказывания» стали носить название символических.

Все современные устройства базируются на операциях логического характера. За счет них происходит обработка и совершение тех или иных манипуляций.

Виды выражений

С помощью логических операций можно строить теории, а также решать сложные задачи, результатом которых окажется справедливый итог. Стоит помнить о том, что прослеживать имеющиеся связи для анализа необходимо крайне внимательно. А еще – учитывать заданные условия, которые относятся к поставленной задаче.

Логические выражения могут быть:

В первом случае результатом обработки заданной операции выступать только «истина» или «ложь». Во втором – или итогом становятся или только истинные операции, или исключительно ложные.

Процедуры получения сложного выражения из нескольких простых имеют определенное название. А именно – формулы логического характера.

Основные операции

Математика, информатика, программирование и другие науки немыслимы без анализа, а также построения теорий по заданным вопросам. Здесь без мышления логического характера не обойтись. Соответствующий момент активно применяется в приложениях — не только сложных, но и элементарных.

Чтобы понять, как работает логи ческая цепочка в калькуляторах истинности, стоит запомнить ключевые операции над логическими выражениями. Всего их несколько:

  • конверсия;
  • дизъюнкция;
  • конъюнкция;
  • строгая дизъюнкция;
  • импликация;
  • эквивалентность.

В программировании также стоит обратить внимание на запись исключающего или. Это – операция XOR.

Порядок обработки

При изучении формулы логики заданных высказываний стоит запомнить порядок (приоритет) обработки операций в сложном выражении. Выполняются манипуляции так:

  • инверсия (логическое отрицание);
  • конъюнкция (логическое умножение);
  • дизъюнкция (логическое сложение);
  • импликация;
  • эквивалентность.

Для того, чтобы изменить прописанный порядок выполнения обработки данных, необходимо в логических выражениях использовать скобки.

Таблицы и операции

Построить таблицу истинности можно без онлайн калькуляторов. Для этого достаточно запомнить, как работает каждая из перечисленных выше операций. У математиков с этим проблем не возникает – они хорошо заучивают предложенную далее информацию.

Конъюнкция

Носит название «логическое И» или «умножение». Часто встречается в программировании. В языках «создания контента» обладает особым обозначением. Примеры записи:

Выражение логического характера при конъюнкции является истиной, только когда оба простых высказывания тоже выступают в качестве правды. Если хотя бы одно из них – ложь, то вся операция примет значение False.

Калькулятор истинности: все о логике для программиста

Выше представлена таблица истинности при операции конъюнкции.

Дизъюнкция

Является сложением. У этого логического выражения есть иное название – «логическое ИЛИ». Тоже встречается в программировании довольно часто.

Может иметь такие формы записи:

Преобразование последовательности будет осуществляться по принципу: выражение – истина, если хотя бы одно из его составляющих – правда. Ложно, когда оба элемента имеют значение FALSE.

Калькулятор истинности: все о логике для программиста

Выше – примеры таблицы истинности, которая работает в отношении дизъюнкции.

Инверсия

Следующий момент, на который стоит обратить внимание – это инверсия. Носит название «отрицание» или «логическое НЕ».

Обозначения в программировании:

Логическое выражение при отрицании обладает следующими особенностями:

Калькулятор истинности: все о логике для программиста

  1. Когда исходные данные истины, то результатом станет ложь.
  2. Если операция обладает значением «ложь», ее отрицание получит «истину».
  3. Можно рассматривать соответствующую манипуляцию как трактовку «Неверно, что…»

Вот такую таблицу истинности можно построить относительно инверсии.

Импликация

При любом логическом выводе стоит опираться на предлагаемые примеры и таблицы. Импликация – это следование.

В любом заданном логическом выражении результат – это истина всегда. Исключение – когда из правды следует ложь. Она связывает два высказывания (a и b), где:

Калькулятор истинности: все о логике для программиста

  • A – это условие, первое выражение;
  • B – следствие.

Если из A может следовать B, значит операция выдаст в результате обработки «истину».

Эквивалентность

Так называют равнозначность. Новое высказывание истинно тогда, когда оба простых выражения – это правда.

Калькулятор истинности: все о логике для программиста

Выше – пример расчетов формулы логики заданных высказываний при эквивалентности.

Исключение

Онлайн калькуляторы могут помочь построить график или указать, что верно, а что нет, без вдумчивости в поставленную задачу со стороны пользователя. Но программистам приходится прописывать принципы функционирования и выполняемые операции вручную. Для них особенности алгебры логики и информатики крайне важны.

Порядок выполнения логических операций ранее был рассмотрен. Осталось понять, как работает исключение.

Согласно установленным правилам, операция будет истиной, когда среди значений переменных A и B есть одно правдивое. Если оба – это действительность, упомянутый принцип работать не будет.

Калькулятор истинности: все о логике для программиста

Исключающее ИЛИ – преобразование, которое носит название «сложение по модулю два».

Законы алгебры логики

Формулы логики высказываний запомнить не так трудно. Но учить соответствующие законы – не всегда оправданный шаг. Для выполнения операций достаточно вспомнить алгебру, а также преобразование выражений.

Калькулятор истинности: все о логике для программиста

Выше – примеры логических операций, упрощенные для запоминания человеком.

Чтобы лучше понять тему

В сети сделано и размещено немало калькуляторов, при помощи которых можно судить об истинности высказываний. Но хороший программист должен самостоятельно уметь производить соответствующие подсчеты. Операцией логического характера не является выражение, результатом которого не выступает:

  • понимание смысла;
  • изменение содержания или объема;
  • образование новых понятий.

Логическое выражение в программировании обычно предусматривает работу с операторами:

А для того, чтобы лучше понимать соответствующую тему, рекомендуется пройти онлайн курсы дистанционно. Они помогут быстрее вникнуть в особенности программирования, коддинга и выбранных языков. По выпуску ученику будет выдан сертификат, указывающий на наличие знаний в выбранном направлении. Так логическое выражение и упомянутые ранее операции не доставят никаких хлопот даже новичку-разработчику.

Хотите освоить современную IT-специальность? Огромный выбор курсов по востребованным IT-направлениям есть в Otus !

Также, возможно, вам будет интересен следующий курс:

Откройте для себя весь потенциал побитовых операторов. Без математики

При изучении нового языка программирования в его документации мы обычно находим таблицу, где перечислены различные операторы, которые можно использовать с числами. Помимо хорошо знакомых нам +, -, * и /, в ней всегда присутствует раздел, который многие пропускают. Я имею ввиду раздел с побитовыми операторами: >, &, ^ и |.

И хотя поначалу они могут казаться туманными, не особо нужными и востребованными только теми, кто пишет на низкоуровневых языках, на деле эти операторы имеют немалое значение. Причём некоторые из наиболее эффективных способов их применения совсем не требуют математики.

Побитовые операторы позволяют управлять двоичным представлением данных, что на деле оказывается очень полезной возможностью. Поэтому предлагаю познакомиться с этим инструментом и научиться грамотно его использовать.

▍ Дайте мне биты

Фундаментально компьютеры понимают только 1 и 0. На уровне же восприятия человеком смысл этим 1 и 0 придаёт контекст. Тут можно провести аналогию со словами в английском языке, смысл которых изменяется в зависимости от контекста. К примеру, слово «present» в зависимости от ситуации может означать «подарок» или «настоящее время».

Одним из типичных примеров, в котором важен контекст двоичного представления, связан с кодированием текста. Если вам доводилось открывать файл с неверной кодировкой, то вы могли видеть в нём символы Null (�). Этот символ используется, когда компьютер не может декодировать определённые строки бит, составляющие текст документа. Переключение на корректную кодировку устранит эти символы, и вы увидите фактический текст файла. Как бы то ни было, для компьютера все файлы являются лишь двоичными представлениями, смысл которым придаёт их формат.

Один бит практически бесполезен для выполнения задач, поэтому обычно мы работаем с их группами. С помощью 2 битов можно представить 2^2 значений, или 4 разных числа, через следующие комбинации:

  • 00
  • 01
  • 10
  • 11
  • 000
  • 001
  • 010
  • 011
  • 100
  • 101
  • 110
  • 111
  1. Полубайт — 4 бита. 2^4, или 16, значений.
  2. Байт — 8 бит. 2^8, или 256, значений.
  3. Слово — 4 байта в 32-битных системах, 8 байтов в 64-битных.

Отличный способ визуализировать общую группу бит – это открыть окно калькулятора Windows, кликнуть по иконке меню в верхнем левом углу и сменить режим со стандартного на режим программиста. Теперь вы будете видеть числа в их шестнадцатеричной (hex), десятичной, восьмеричной и двоичной формах. Над кнопкой битового сдвига >> можно ограничить максимальный/минимальный целочисленный размер, который может вместиться в байт, слово, двойное слово и так далее.

Вы даже можете переключиться в двоичный режим, кликнув по кнопке из точек, расположенной под BIN -форматом значения, чтобы получить возможность самостоятельно инвертировать биты. Это позволит вам выработать более интуитивное понимание представления 0 и 1, а также понять, как они переводятся в другие численные форматы.

Целые числа являются знаковыми, то есть поддерживают как положительный, так и отрицательный диапазоны

Для пользователей Linux отдельно скажу, что в этой системе аналогичную функциональность реализует приложение gnome-calculator.

В MacOS режим программиста в калькуляторе можно запустить путём ввода в стандартном режиме ⌘ и числа 3.

Кодирование чисел в двоичную форму обеспечивает уникальное преимущество перед их десятичным представлением. Такая кодировка позволяет использовать само двоичное представление в качестве своеобразной команды, в которой сегменты двоичного числа соответствуют определённой функциональности. Инвертируя различные единицы и нули, можно управлять программой эффективным и компактным способом при относительно небольших размерах чисел.

Разберём пример. Предположим, у нас есть байт данных (пробел здесь только для лучшей читаемости), 0010 0011 , и мы хотим получить число, в котором установлены только 2 младших бита – 0000 0011 . Как это можно сделать? С помощью логической операции И (AND), которая реализуется через символ амперсанда & .

Но прежде, чем мы сможем получить итоговый результат, нам нужно создать ещё одно двоичное число, которое называется маской. Маска – это двоичное число, в котором определённые биты установлены как 1 или 0, чтобы при использовании с побитовым оператором нужным образом маскировать элементы исходного двоичного числа. Вот пример:

0010 0011 (исходное значение) & -> 0000 0011 (итоговое значение) 0000 0011 (маска)

Каковы будут десятичные представления этих 3 двоичных чисел? Это не важно. Нам важно лишь, чтобы определённые биты в итоговом двоичном числе оказались 1 или 0. Реализуется это таким образом – операция & сравнивает биты в каждом индексе двух чисел, создавая в результате нуль или единицу. Вот правила, по которым работает это сравнение:

  1. Если оба бита 0, то итоговый бит равен 0.
  2. Если оба бита 1, то итоговый равен 1.
  3. Если один бит 0, а второй 1, то итоговый будет равен 0.

Разберём ещё один пример. Предположим, у нас есть байт 1011 0011 , и мы хотим получить другой байт – 1011 0000 . Получается, нам нужно инвертировать два последних бита. На секунду обратитесь к перечисленным правилам, чтобы придумать подходящую маску самостоятельно. А теперь взгляните на пример ниже:

1011 0011 & -> 1011 0000 1011 0000

Если вы придумали правильную маску, то можете себя похвалить. Если же ошиблись, то ничего страшного, это новая тема, и на её усвоение может потребоваться некоторое время. Я хочу ещё раз подчеркнуть, что нам не нужно знать десятичные представления этих чисел, как и то, каким будет математический результат этих операций. Здесь мы просто создаём маски, которые позволят получить желаемые битовые паттерны.

▍ Побитовое ИЛИ (OR)

Мы разобрали использование побитового оператора & для маскирования битов исходного двоичного числа в состояние 0, но что, если нам нужно, наоборот, установить определённые биты на 1? В таком случае мы используем символ | для выполнения побитовой операции ИЛИ. Если, взяв предыдущий пример, мы захотим, чтобы результат был 1011 1111 , то можем инвертировать два нуля в единицы с помощью ИЛИ. Для начала нужно создать маску с 1 в нужных нам позициях, после чего её применить.

1011 0011 | -> 1011 1111 1011 1111

Обратившись к правилам побитовой операции И, мы видим, что они аналогичны правилам операции ИЛИ за исключением последнего:

  1. Если оба бита 0, то итоговый бит равен 0.
  2. Если оба бита 1, то итоговый равен 1.
  3. Если один бит 0, а второй 1, то итоговый будет равен 1.

▍ Побитовое НЕ

Оператор НЕ обозначается тильдой ~ . Он используется для инвертирования всех битов в противоположное состояние. Его можно назвать особенным, поскольку он не требует маски для своего применения. Этот оператор относится к унарным, что отличает его от таких операторов, как – или +, которые являются бинарными. В этом случае бинарность означает не то, что они работают только для двоичных чисел, а то, что для их функционирования необходимо два числа. Как видите, тут снова всплывает значимость контекста.

Принцип работы НЕ весьма прост. Если бит равен 1, то он становится 0, и наоборот. Обычно этот приём используется для создания маски, которая применяется совместно с оператором & . Предположим, что у нас есть число 0101 0010 , и мы хотим инвертировать в нём первую 1, чтобы получить 0001 0010 . Сначала мы создаём двоичное число, которое содержит 1 в интересующей нас позиции, 0100 0000 . Затем мы это число инвертируем

0100 0000 ~ -> 1011 1111

Как видите, в результате инвертирования все 0 стали 1, а все 1 – 0. Теперь можно взять полученное число 1011 1111 и использовать его в качестве маски через оператор & для исходного числа 0101 0010 .

0101 0010 & -> 0001 0010 1011 1111

Далее мы создаём нужное нам двоичное число, где первая 1 оказывается инвертирована в 0.

▍ Исключающее ИЛИ (XOR)

В операции исключающее ИЛИ используется символ ^ . Эта операция применяется, когда необходимо инвертировать определённые биты. Например, если нам нужно инвертировать вторую 1 в числе 1001 0111 , то мы построим маску, где укажем 1 в соответствующей позиции.

1001 0111 ^ -> 1000 0111 0001 0000

Если взять полученное число 1000 0111 и выполнить для него XOR с прежней маской 0001 0000 , то мы получим исходное число.

1000 0111 ^ -> 1001 0111 0001 0000

В этом случае XOR сравнивает каждый бит и в случае их отличия возвращает 1, а в случае совпадения – 0. В большинстве контекстов это означает, что нужно создать маску, которая будет содержать 1 в тех позициях, которые требуется инвертировать. Остальные биты маски нужно оставить равными 0.

▍ Сдвиг

Возьмём, к примеру, десятичное число 123,456. Относительно него нам известно, что наименьшую значимость в нём имеет цифра 6, потому что она находится в позиции исчисления единиц. При этом наибольшей цифрой выступает 1, поскольку занимает позицию исчисления сотен тысяч. В двоичных числах всё аналогично. Если читать полубайт 1110 справа налево, то 0 окажется наименее значимым, а последняя 1 слева – наиболее значимой. Если выполнить сдвиг влево на 4, то мы, по сути, прибавим 4 нуля к наименее значимой стороне числа. В результате получится следующее:

1110 1110 0000

Как вы могли догадаться, если сдвиг двоичного числа влево приписывает нули к наименее значимой стороне, то сдвиг вправо припишет их к наиболее значимой. Тогда при использовании того же исходного числа мы получим:

1110 >> 4 -> 0000

Представить операцию сдвига можно не только как прибавление нулей с одной или другой стороны, но и как то, что эти нули сдвигают исходное двоичное число влево или вправо. Отсюда и её название.

В этой статье мы никак не затрагиваем математические аспекты, но забавно то, что сдвиг влево числа на 1 равнозначен умножению числа на 2^1, то есть его удваиванию. Сдвиг влево на 2 будет равнозначен умножению числа на 2^2, то есть его учетверению. И так далее.

Сдвиг вправо ведёт к противоположному результату. При использовании тех же приведённых выше чисел он половинит число или делит его на 4. Если вам нужно поделить или умножить число на степень 2, то операция сдвига окажется для этого очень быстрым решением. При этом она является типичной оптимизацией, выполняемой внутренне во время компиляции программ. Хотя для наших целей мы рассматриваем этот оператор просто как прибавляющий 0 в начало или конец двоичного числа или как смещающий это число влево/вправо на указанное количество нулей.

▍ Какая от этого польза?

Помимо нескольких грамотных приёмов оптимизации, как ещё можно использовать эти операторы на практике? Чтобы ответить на этот вопрос, нам нужно познакомиться с ещё одним принципом – шестнадцатеричными числами.

Шестнадцатеричные числа представляют альтернативный способ выражения чисел в вычислительной технике. В отличие от двоичных, которые имеют основание 2, эти числа имеют основание 16. Это означает, что в них используется уже не две цифры – 0 и 1 – а 16 символов, которые включают цифры от 0 до 9, а также буквы A, B, C, D, E и F, выражающие 10, 11, 12, 13, 14 и 15.

В вычислительной технике hex-числа важны тем, что позволяют более сжато выражать двоичные числа. Одно hex-значение может выразить четыре двоичных цифры (полубайт), то есть с помощью двух можно представить целый байт. Во многих языках программирования hex-числа обозначаются путём добавления приставки 0x , позволяющей отличать их от двоичных и десятичных значений. Получается, если вы захотите представить число 1234 в шестнадцатеричном виде, то его нужно будет записать как 0х1234.

Внимание. Не нужно путать десятичное число 1234 и шестнадцатеричное 0х1234. Первое – это десятичное значение 1,234, а второе – это десятичное значение 4,660.

Чтобы преобразовать двоичное число в шестнадцатеричное, нужно разбить его на группы полубайтов, начиная с правой стороны, и затем заменить каждый полубайт соответствующей hex-цифрой.

Например, двоичное число 1101 1010 можно разбить на 1101 и 1010 . Преобразование каждой группы в шестнадцатеричное значение даст DA . Следовательно, двоичное представление 1101 1010 равнозначно шестнадцатеричному 0хDA . Если же у вас под рукой всё ещё запущен калькулятор в режиме программиста, то эти вычисления можно поручить ему. Просто введите двоичную форму числа, и он сообщит вам его hex-эквивалент.

Шестнадцатеричные числа также используются в вычислительной технике для представления адресов памяти. Дело в том, что эти адреса обычно выражаются в виде 32- или 64-битных чисел, которые могут быть довольно длинными и сложными для чтения в двоичном виде. Представляя адреса памяти в hex-форме, мы делаем их более сжатыми и простыми для восприятия. Ниже показан пример DA в виде 32-битного двоичного числа:

0000 0000 0000 0000 0000 0000 1101 1010 vs 0000 00DA

▍ Побитовые операторы в эмуляторах

Теперь, обладая всей этой информацией, мы можем разобрать типичный практический случай – интерпретатор Chip-8. Этот интерпретатор станет хорошим стартовым проектом для людей, только начинающих знакомство с эмуляцией. В нём используется всего 36 инструкций, каждая длиной 2 байта, или 16 бит. Поскольку работать с 16 битами в двоичной форме сложно, мы будем представлять их в шестнадцатеричном виде. Напомню, что каждое шестнадцатеричное значение имеет размер 4 бита. И это удобно, потому что минимальный сегмент инструкции Chip-8, с которым нам придётся работать, составляет 4 бита.

Игра Space Intercept, запущенная на Telmac 1800 через эмулятор Chip-8 (Джозеф Уэйсбекер, 1978 год)

Также нужно иметь ввиду, что инструкции отличаются своими компонентами. Справка по Chip-8 от Cowdog прекрасно поясняет действия каждой из них. Разберём простой случай с инструкциями, которые относятся к диапазону 0х1000 . В качестве примера мы будем использовать эмулятор Crystal Chip-8. Напомню, что эти числа представлены в hex-виде.

case op & 0xF000 #nnn или addr - A 12-битное значение, младшие 12 бит инструкции. #n или nibble - A 4-битное значение, младшие 4 бита инструкции. #x – 4-битное значение, младшие 4 бита старшего байта инструкции. #y – 4-битное значение, старшие 4 бита младшего байта инструкции. #kk или byte – 8-битное значение, младшие 8 бит инструкции. when 0x1000 #1nnn #установить счётчик команд на nnn, представляющее 3 младших байта. @pc = op & 0x0FFF;

Предполагая, что нам представлена инструкция 0x1ABC , сначала нужно определить её наиболее значимый байт. Это позволит понять, как его интерпретировать. Обратившись к документации Cowdog, мы видим, что инструкции, содержащие в качестве наиболее значимого байта 1, устанавливают счётчик команд на последние 12 бит инструкции. При определении инструкции нам нужно сохранить наиболее значимый бит и очистить остальные 12, которые нас не интересуют. Этот процесс должен быть вам знаком.

Можно написать оператор условия, который позволит нам создать несколько ветвлений на основе получаемой инструкции. Мы возьмём код операции 0x1ABC и выполним побитовую операцию & с маской 0xF000 , чтобы получить наиболее значимый бит нашей инструкции 0x1000 . Это гарантирует, что любая входящая инструкция, которая начинается с 0x1 , всегда будет отправлена по верной ветви, будь это 0x1DDD , 0x1012 и так далее.

Теперь, когда мы организовали правильное перенаправление инструкции, нужно получить её младшие 12 бит и установить наш счётчик команд на это значение. Опять же, для этого можно использовать & . Выполнив & для нашего кода операции и маски 0x0FFF , мы получим число 0x0ABC . Затем можно добавить это число в наш счётчик команд.

Вас может несколько запутать процесс перевода шестнадцатеричных значений обратно в двоичные, как мы делали в предыдущих примерах. Для большей ясности я покажу, как это происходит в текущем примере. Здесь 0x1ABC переводится в 0001 1010 1011 1100 , а 0xF000 переводится в 1111 0000 0000 0000 .

Выполнив для этих чисел операцию & , мы получим:

0001 1010 1011 1100 & -> 0001 0000 0000 0000 1111 0000 0000 0000

Результатом стало значение 0001 0000 0000 0000 , которое просто является кодом операции с наиболее значимым битом. Как вы могли догадаться, 0001 0000 0000 0000 – это 0x1000 в двоичном виде, почему оно и отправляется по ветви 0x1000 нашего оператора ветвления.

Та же логика касается и получения младших 12 бит нашей операции. В этом случае нас интересуют все числа, кроме первых 4 бит, поэтому их нужно убрать. На сей раз мы используем значение 0x0FFF , которое переводится в 0000 1111 1111 1111 . Выполнив для него побитовое & , мы получим:

0001 1010 1011 1100 & -> 0000 1010 1011 1100 0000 1111 1111 1111

И это как раз то, что нам нужно. Последний вопрос, который у вас мог остаться: «Почему мы используем в hex-числе F , а не 1, как в двоичном?» Дело в том, что F в двоичном виде соответствует 1111 . Поэтому, если нам нужно сохранить этот битовый паттерн в данном индексе нашего исходного hex-значения, то можно просто использовать в нём F .

Какой бы ни была комбинация 0 и 1 – при выполнении & она всегда будет сохранена. Поскольку мы хотели сохранить последние 12 бит нашего hex-значения, мы указали в нём три F . А так как для перехода по нужной ветви оператора ветвления нужно было сохранить только битовый паттерн наиболее значимых 4 бит, мы указали всего одну F в первой позиции hex-маски.

Закончим эту тему ещё одним примером, в котором используются операторы сдвига.

when 0x5000 #5xy0 #Пропустить следующую инструкцию, если Vx = Vy. #Сравнивает регистр Vx с регистром Vy. #Если они равны, инкрементирует счётчик команд на 2. x = (op & 0x0F00) >> 8 y = (op & 0x00F0) >> 4 #индекс регистра if @reg[x] == @reg[y] @pc +=2 end

Предположим, что наша следующая инструкция – это 0x5120 . Нам нужно создать маску, которая будет направлять нашу операцию по ветви 0x5000 оператора ветвления. Для её создания нужно сохранить наиболее значимую цифру (первую hex-цифру), установив все остальные на 0. Попробуйте самостоятельно разобраться, как это сделать.

Далее мы видим, что инструкции, относящиеся к диапазону 0x5000 , дают нам значения x и y, которые можно использовать для обращения к регистрам в x и y. Следовательно, нам нужно каким-то образом получить из операции эти значения. Также, как в предыдущих примерах, можно поместить F по индексу интересующего нас hex-значения и 0 в остальных индексах. Для значения x это будет маска 0x0F00 , а для значения y — – 0x00F0 .

Мы узнали, что сдвиг вправо прибавляет 0 к наиболее значимой стороне двоичного числа. И хотя в большинстве случаев это верно, что должно происходить, когда ваше число имеет фиксированную длину? В Chip-8 минимальная двоичная инструкция соответствует 0000 0000 0000 0000 , а максимальная – 1111 1111 1111 1111 . В обоих случаях они ограничены 16 битами. Здесь мы не можем просто прибавить нули к наиболее значимой стороне, например так: 0000 1111 1111 1111 1111 , поскольку тогда мы получим уже 20-битную инструкцию при том, что Chip-8 поддерживает лишь 16-битные. Придётся чем-то пожертвовать.

Работает это в данном случае так. Числа с наименее значимой стороны вытесняются, освобождая место для нулей с наиболее значимой стороны. Это означает, что число 1111 1111 1111 1111 при сдвиге вправо на 4 станет:

(1111 1111 1111 1111 >> 4) 0000 1111 1111 1111

Сегмент 1111 был вытеснен для освобождения места под 0000 . Сколько раз нам нужно сдвинуть инструкцию вправо, чтобы получить x и y? Если взглянуть на шаблон инструкции для инструкций 0x5000 – 5xy0 – мы увидим, что x смещён от наименее значимой стороны на 8 бит. Поскольку один сдвиг перемещает целое число на 1 бит, то для перемещения x к наименее значимой стороне двоичного числа потребуется 8 таких сдвигов. А поскольку y находится всего в 4 битах от наименее значимой стороны инструкции, то для него потребуется лишь 4 сдвига. Таким образом, чтобы получить значения x и y, мы выполняем сдвиг на 8 и на 4 соответственно.

 x = (op & 0x0F00) >> 8 y = (op & 0x00F0) >> 4

После получения значений x и y следующим действием будет сравнение нашего регистра в x с регистром в y на предмет их равенства. Если они равны, то мы инкрементируем счётчик команд.

 #индекс регистра if @reg[x] == @reg[y] @pc +=2 end

Здесь я не буду разбирать все инструкции, поскольку это получится очень долго, но если взглянуть на некоторые инструкции для Chip-8, например, на расположенные в диапазоне 0x8000 :

8xy1 - OR Vx, Vy Set Vx = Vx OR Vy. 8xy3 - XOR Vx, Vy Set Vx = Vx XOR Vy.

То вы увидите, что в итоге мы используем все побитовые функции, с которыми познакомились в первой части статьи. Надеюсь, этот материал позволил вам понять важность побитовых операторов в программировании, а также послужил практическим примером их конкретного использования.

Эмуляторы – это не единственный случай применения, поэтому я рекомендую поискать и другие. Но в следующий раз, когда вы будете запускать свой эмулятор с легально полученными или собственными образами ROM, помните, что за его работой стоят побитовые операторы.

Если вы хотите получше разобраться в принципах работы эмуляторов, то советую создать собственный интерпретатор Chip-8, поскольку это будет очень ценным опытом. В качестве же справочного материала советую обращаться к документации от Cowdog, которая лично в моём опыте с Chip-8 оказала бесценную помощь.

  • ruvds_перевод
  • битовые операторы
  • chip-8
  • двоичные числа
  • шестнадцатеричные числа
  • инвертирование бит

Основные логические операции. AND, NOT, OR и XOR (исключающее или)

В этой статье мы поговорим о некоторых битовых операциях. Рассмотрим основные из них: XOR (исключающее ИЛИ), AND (И), NOT (НЕ) а также OR (ИЛИ).

Как известно, минимальной единицей измерения информации является бит, который хранит одно из 2-х значений: 0 (False, ложь) либо 1 (True, истина). Таким образом, битовая ячейка может одновременно находиться лишь в одном из двух возможных состояний.

Для манипуляций с битами используют определённые операции — логические или булевые. Они могут применяться к любому биту, вне зависимости от того, какое у него значение — ноль или единица. Что же, давайте посмотрим на примеры использования трёх основных логических операций.

Логическая операция AND (и)

AND обозначается знаком & .

Оператор AND выполняется с 2-мя битами, возьмём, к примеру, a и b. Результат выполнения операции AND равен 1, если a и b равняются 1. В остальных случаях результат равен 0. Например, с помощью AND вы можете узнать, чётное число или нет.

Посмотрите на таблицу истинности операции AND:

1-20219-a11fa6.jpg

Логическая операция OR (ИЛИ)

Оператор OR также выполняется с 2-мя битами (a и b). Результат равен 0, если a и b равны 0, иначе он равен 1. Смотрим таблицу истинности.

2-20219-a4e8af.jpg

Логическая операция XOR (исключающее ИЛИ)

Оператор XOR обозначается ^ .

XOR выполняется с 2-мя битами (a и b). Результат выполнения операции XOR (исключающее ИЛИ) равен 1, когда один из битов b или a равен 1. В остальных ситуациях результат применения оператора XOR равен 0.

Таблица истинности логической операции для XOR (исключающее ИЛИ) выглядит так:

3-20219-7c562b.jpg

Используя XOR (исключающее ИЛИ), вы можете поменять значения 2-х переменных одинакового типа данных, не используя временную переменную. А ещё, посредством XOR можно зашифровать текст, например:

String msg = «This is a message»; char[] message = msg.toCharArray(); String key = «.*)»; String encryptedString = new String(); for(int i = 0; i

Согласен, XOR — далеко не самый надёжный метод шифрования, но это не значит, что его нельзя сделать частью какого-либо шифровального алгоритма.

Логическая операция NOT (НЕ)

Это побитовое отрицание, поэтому выполняется с одним битом и обозначается ~ .

Результат зависит от состояния бита. Если он в нулевом состоянии, то итог операции — единица и наоборот. Всё предельно просто.

4-20219-fd7aab.jpg

Эти 4 логические операции следует запомнить в первую очередь, т. к. с их помощью можно получить практически любой возможный результат. Также существуют такие операции, как > (побитовый сдвиг вправо).

Исключающий или

Exclusive или или исключительная дизъюнкция — это логическая операция, которая выводит истину только в том случае, если входные данные различаются (один — истина, другой — ложь).

Это символизируется префиксным оператором J и инфиксным операторами XOR (или ), EOR, EXOR, ⊻, ⩒, ⩛, ⊕, ↮ и ≢ . отрицание операции XOR — это логический двусмысленный, который выводит истину только тогда, когда два входа одинаковы.

Он получает название «исключающее ИЛИ», потому что значение «или» неоднозначно, когда оба операнда истинны; исключительный оператор or исключает этот случай. Иногда это воспринимается как «одно или другое, но не оба сразу». Это можно было бы записать как «А или В, но не А и В».

В более общем смысле, XOR истинно только тогда, когда истинно нечетное количество входов. Цепочка XOR — XOR b XOR c XOR d (и так далее) — истинна, когда нечетное количество входов истинно, и ложно, когда четное количество входов истинно.

Таблица истинности

Аргументы слева объединены с помощью XOR. Это двоичная матрица Уолша (см. код Адамара ).

таблица истинности A XOR B показывает, что она выводит истину всякий раз, когда входные данные различаются:

XOR таблица истинности

Вход Выход
A B
0 0 0
0 1 1
1 0 1
1 1 0
  • 0, ложь
  • 1, истина

Эквивалентности, исключение и введение

Исключительная дизъюнкция по существу означает «любой, но не оба и ни один ». Другими словами, утверждение истинно тогда и только тогда, когда одно истинно, а другое ложно. Например, если две лошади участвуют в гонке, то одна из двух будет выиграть гонку, но не оба. Исключительная дизъюнкция p ⊕ q , также обозначается p ⩛ q или J ⁡ pq pq> , может быть выражено в терминах логического соединения («логическое и», ∧ ), дизъюнкция («логическое ИЛИ», ∨ ), а отрицание ( ¬ ) следующим образом:

p ⊕ q = (p ∨ q) ∧ ¬ (p ∧ q) p \ oplus q = (p \ lor q) \ land \ lnot (p \ land q) \ end >>

Исключительная дизъюнкция p ⊕ q также можно выразить следующим образом:

p ⊕ q = (p ∧ ¬ q) ∨ (¬ p ∧ q) p \ oplus q = (p \ land \ lnot q) \ lor (\ lnot p \ land q) \ end >>

Это представление XOR может оказаться полезным при построении схемы или сети, поскольку оно имеет только одна операция ¬ и небольшое количество ∧ и ∨ операции. Доказательство этого тождества приведено ниже:

p ⊕ q = (p ∧ ¬ q) ∨ (¬ p ∧ q) = ((p ∧ ¬ q) ∨ ¬ p) ∧ ((p ∧ ¬ q) ∨ q) = ((p ∨ ¬ p) ∧ (¬ q ∨ ¬ p)) ∧ ((p ∨ q) ∧ (¬ q ∨ q)) = (¬ p ∨ ¬ q) ∧ (p ∨ q) = ¬ (п ∧ Q) ∧ (п ∨ Q) p \ oplus q = (p \ land \ lnot q) \ lor (\ lnot p \ land q) \\ [3pt ] = ((p \ land \ lnot q) \ lor \ lnot p) \ land ((p \ land \ lnot q) \ lor q) \\ [3pt] = ((p \ lor \ lnot p) \ land (\ lnot q \ lor \ lnot p)) \ land ((p \ lor q) \ land (\ lnot q \ lor q)) \\ [3pt] = (\ lnot p \ lor \ lnot q) \ land (p \ lor q) \\ [3pt] = \ lnot (p \ land q) \ land (p \ lor q) \ end >>

Иногда бывает полезно записать p ⊕ q следующим образом:

p ⊕ q = ¬ ((p ∧ q) ∨ (¬ п ∧ ¬ q)) p \ oplus q = \ lnot ((p \ land q) \ lor (\ lnot p \ land \ lnot q)) \ end >>

п ⊕ q = (п ∨ q) ∧ (¬ p ∨ ¬ q) p \ oplus q = (p \ lor q) \ land (\ lnot p \ lor \ lnot q) \ end >>

Это эквивалентность может быть установлена, применяя законы Де Моргана дважды к четвертой строке приведенного выше доказательства.

Исключающее или также эквивалентно отрицанию логического двусмысленного по правилам материальной импликации (материальное условное эквивалентно дизъюнкции отрицания его предшествующего и его следствия) и материальной эквивалентности.

Таким образом, в математической и инженерной нотации имеем:

p ⊕ q = (p ∧ ¬ q) ∨ ( ¬ p ∧ q) = pq ¯ + p ¯ q = (p ∨ q) ∧ (¬ p ∨ ¬ q) = (p + q) (p ¯ + q ¯) = (p ∨ q) ∧ ¬ (p ∧ q) знак равно (p + q) (pq ¯) p \ oplus q = (p \ land \ lnot q) \ lor (\ lnot p \ land q) = p > + > q \\ [3pt] = (p \ lor q) \ land (\ lnot p \ lor \ lnot q) = (p + q) (> + >) \\ [3pt] = (p \ lor q) \ land \ lnot (p \ land q) = (p + q) (>) \ end >>

Отношение к современной алгебре

Хотя операторы ∧ (соединение ) и ∨ (дизъюнкция ) являются очень полезны в логических системах, они не позволяют получить более обобщаемую структуру следующим образом:

Системы (, ∧) , \ клин)> и (, ∨) , \ lor)> являются моноидами, но ни одна из них не является группой . К сожалению, это предотвращает объединение этих двух систем в более крупные структуры, такие как математическое кольцо.

. Однако система, использующая исключающее или (, ⊕) , \ oplus)> — абелева группа. Комбинация операторов ∧ и ⊕ над элементами > создает хорошо известное поле F 2 > . Это поле может представлять любую логику, доступную с помощью системы (∧, ∨) , и имеет дополнительное преимущество в виде арсенала инструментов алгебраического анализа для полей.

Более конкретно, если связать F с 0 и T с 1, можно интерпретировать логическую операцию «И» как умножение на F 2 > и операцию «XOR» как сложение на F 2 > :

r = p ∧ q ⇔ r = p ⋅ q (mod 2) r = p ⊕ q ⇔ r = p + q (mod 2) r = p \ land q \ Leftrightarrow r = p \ cdot q > \\ [3pt] r = p \ oplus q \ Leftrightarrow r = p + q > \\\ end >>

Использование этого базиса для описания логической системы называется алгебраической нормальной формой.

Exclusive «или» на английском языке

Оксфордский словарь английского языка объясняет «либо. или» следующим образом:

Основная функция того и другого состоит в том, чтобы подчеркнуть полное безразличие двух (или более) вещей или направлений. ; но второстепенная функция состоит в том, чтобы подчеркнуть взаимную исключительность, = одного из двух, но не обоих.

Исключающее-или явно заявляет «одно или другое, но не ни то, ни другое». Однако соответствие отображения между формальными логическими операторами и конъюнкциями естественного языка далеко не просто или однозначно, и десятилетиями изучается в лингвистике и аналитической философии..

Следуя такой интуиции здравого смысла насчет «или», иногда утверждают, что во многих естественных языках, английском включая, слово «или» имеет «исключительный» смысл. Исключительная дизъюнкция пары предложений (p, q) должна означать, что p истинно или q истинно, но не то и другое вместе. Например, можно утверждать, что обычное намерение такого утверждения, как «Вы можете выпить кофе, или вы можете выпить чай», состоит в том, чтобы оговорить, что точно одно из условий может быть истинным. Конечно, при некоторых обстоятельствах предложение, подобное этому примеру, следует воспринимать как запрещающее возможность принятия обоих вариантов.

В английском языке конструкция «либо. или» обычно используется для обозначения исключающего или, а «или» обычно используется для включения. Но в испанском языке слово «o» (или) может использоваться в форме «p o q» (включительно) или в форме «o p o q» (исключая). Некоторые могут утверждать, что любое двоичное или другое n-арное исключающее «ИЛИ» истинно тогда и только тогда, когда оно имеет нечетное число истинных входов (однако это не единственное разумное определение; например, цифровые элементы xor с несколькими входами обычно не используют это определение), и что в английском языке нет соединения, которое имеет это общее свойство. Например, Барретт и Стеннер утверждают в статье 1971 года «Миф об исключительном« ИЛИ »(Mind, 80 (317), 116–121), что ни один автор не привел пример английского или-предложения, которое, как представляется, false, потому что оба его входных значения верны, и отмахиваются от или-предложений, таких как «Лампочка горит или не горит», как отражающих конкретные факты о мире, а не природу слова «или». Однако «парадокс цирюльника » — каждый в городе бреется или бреется парикмахером, который бреет парикмахера? — не был бы парадоксальным, если бы «или» не могло быть исключительным (хотя пурист мог бы сказать что «либо» требуется в формулировке парадокса).

Альтернативные символы

Символ, используемый для исключительной дизъюнкции, меняется от одной области приложения к другой и даже зависит от свойств, которые подчеркиваются в данном контексте обсуждения. В дополнение к аббревиатуре «XOR» можно также увидеть любой из следующих символов:

  • + , знак плюс, который имеет то преимущество, что все обычные алгебраические свойства математических колец и поля можно использовать без лишних слов; но знак плюс также используется для инклюзивной дизъюнкции в некоторых системах записи; обратите внимание, что исключительная дизъюнкция соответствует сложениюпо модулю 2, которое имеет следующую таблицу сложения, явно изоморфную приведенной выше:
p q p + q
0 0 0
0 1 1
1 0 1
1 1 0
  • ⊕ , измененный знак плюса; этот символ также используется в математике для прямой суммы алгебраических структур
  • J , как в Jpq
  • Инклюзивный символ дизъюнкции ( ∨ ), который каким-либо образом изменен, например
    • ∨ _ >>
    • ∨ ˙ >>
  • ^ , каретка, используется в нескольких языках программирования, таких как C, C ++, C#, D, Java, Perl, Ruby, PHP и Python, обозначающие побитовый оператор XOR; не используется вне контекста программирования, поскольку его слишком легко спутать с другими вариантами использования символа вставки
  • , иногда записываемого как
    • >
    • >-
  • =1 , в символах IEC

Свойства

A ⊕ B

B ⊕ A

A

(B ⊕ C)

(A ⊕ B)

C

Исключающее или не распределяется по какой-либо бинарной функции (даже самой себе), а логическая конъюнкция распределяется по исключающему или. C ∧ (A ⊕ B) знак равно (C ∧ A) ⊕ (C ∧ B) (Соединение и исключающие или образуют операции умножения и сложения поля GF (2), и, как и в любом другом поле, они подчиняются закону распределения.)

A

A

0

A

A → B

(A ⊕ C)

(B ⊕ C)

Когда все входы верны, выход неверен.

A ∧ B

A ⊕ B

Когда все входы ложны, выход ложен.

A ⊕ B

A ∨ B

Функция линейная.

При использовании двоичного для значений true (1) и false (0), то исключающее или работает точно так же, как addition по модулю 2.

Информатика

Традиционное символическое представление логического элемента XOR

Побитовая операция

Nimber сложение является исключающим ИЛИ неотрицательных целых чисел в двоичное представление. Это также векторное сложение в (Z / 2 Z) 4 / 2 \ mathbb ) ^ > .

Исключительная дизъюнкция часто используется для побитовых операций.. Примеры:

  • 1 XOR 1 = 0
  • 1 XOR 0 = 1
  • 0 XOR 1 = 1
  • 0 XOR 0 = 0
  • 11102 XOR 10012 = 01112 (это эквивалентно сложению без переноса )

Как отмечалось выше, поскольку исключительная дизъюнкция идентична сложению по модулю 2, побитовая исключительная дизъюнкция двух n-битных строк идентична стандартному вектору сложения в векторном пространстве (Z / 2 Z) n / 2 \ mathbb ) ^ > .

Исключительно в информатике У дизъюнкции есть несколько применений:

  • Он сообщает, не равны ли два бита.
  • Это необязательный переворот битов (решающий вход выбирает, инвертировать ли входные данные).
  • Он сообщает существует ли нечетное количество 1 бит ( A ⊕ B ⊕ C ⊕ D ⊕ E истинно , если истинно нечетное число переменных).

В логических схемах простой сумматор может быть выполнен с помощью элемента XOR, чтобы сложить числа и сер элементы логических элементов И, ИЛИ и НЕ для создания вывода переноса.

На некоторых компьютерных архитектурах более эффективно хранить ноль в регистре, выполняя операцию «исключающее ИЛИ» с самим собой (биты, исключающие ИЛИ с самим собой, всегда равны нулю) вместо загрузки и сохранения нулевого значения.

В простых пороговых активированных нейронных сетях для моделирования функции XOR требуется второй уровень, поскольку XOR не является линейно разделимой функцией.

Exclusive-or иногда используется как простая функция смешивания в криптографии, например, с одноразовым блокнотом или системами Feistel network.

Exclusive-or также активно используется в блочных шифрах, таких как AES (Rijndael) или Serpent, и в реализации блочного шифра (CBC, CFB, OFB или CTR).

Аналогично, XOR может использоваться при генерации пулов энтропии для аппаратных генераторов случайных чисел. Операция XOR сохраняет случайность, что означает, что случайный бит, обработанный XOR с неслучайным битом, приведет к случайному биту. Несколько источников потенциально случайных данных можно объединить с помощью XOR, и непредсказуемость вывода гарантированно будет не хуже, чем у лучшего отдельного источника.

XOR используется в RAID 3 –6 для создания информации о четности. Например, RAID может «выполнить резервное копирование» байтов 100111002 и 011011002 с двух (или более) жестких дисков, выполняя операцию «исключающее ИЛИ» только что упомянутых байтов, в результате чего получается (111100002) и записывается на другой диск. Согласно этому методу, если один из трех жестких дисков потерян, потерянный байт может быть воссоздан путем операции XOR с байтами оставшихся дисков. Например, если диск, содержащий 011011002, потерян, 100111002 и 111100002 могут быть подвергнуты операции XOR для восстановления потерянного байта.

XOR также используется для обнаружения переполнения в результате двоичной арифметической операции со знаком. Если крайний левый оставшийся бит результата не совпадает с бесконечным числом цифр слева, это означает, что произошло переполнение. Выполнение XOR этих двух битов даст «1», если произойдет переполнение.

XOR можно использовать для обмена двумя числовыми переменными в компьютерах, используя алгоритм обмена XOR ; однако это считается скорее любопытством и на практике не поощряется.

Связанные списки XOR используют свойства XOR для экономии места для представления структур данных двусвязного списка.

В компьютерной графике методы рисования на основе XOR часто используются для управления такими элементами, как ограничительные рамки и курсоры в системах без альфа-каналы или плоскости наложения.

Encodings

Помимо кодов ASCII, оператор кодируется как U + 22BB ⊻ XOR (HTML ⊻ · ⊻ ) и U + 2295 ⊕ CIRCLED PLUS (HTML ⊕ · ⊕, ⊕ ), оба в блоке математических операторов.

См. Также

  • Условное обозначение материала • (Парадокс)
  • Подтверждение дизъюнкции
  • Ampheck
  • Булева алгебра (логика)
  • Логическая область
  • Логическая функция
  • Логическая функция
  • Управляемый вентиль НЕ
  • Дизъюнктивный силлогизм
  • Логика первого порядка
  • Инклюзивная или
  • Инволюция
  • Список тем булевой алгебры
  • Логический график
  • Логическое значение
  • Операция
  • Бит четности
  • Исчисление высказываний
  • Правило 90
  • Симметричное различие
  • Шифр ​​XOR
  • Шлюз XOR
  • Связанный список XOR

Примечания

  1. ^Germundsson, Roger; Вайсштейн, Эрик. «XOR». MathWorld. Исследование Вольфрама. Проверено 17 июня 2015 г.
  2. ^Крейг, Эдвард, изд. (1998), Энциклопедия философии Рутледж, 10, Taylor Francis, p. 496, ISBN 9780415073103
  3. ^или, соедини 2 (нареч. 3) 2a Оксфордский словарь английского языка, второе издание (1989). OED Online.
  4. ^Дженнингс цитирует многочисленных авторов, утверждающих, что слово «или» имеет исключительный смысл. См. Главу 3, «Первый миф об« Или »»:. Дженнингс, Р. Э. (1994). Генеалогия дизъюнкции. Нью-Йорк: Oxford University Press.
  5. ^Дэвис, Роберт Б. (28 февраля 2002 г.). «Исключающее ИЛИ (XOR) и аппаратные генераторы случайных чисел» (PDF). Проверено 28 августа 2013 г.
  6. ^Нобель, Рикард (26 июля 2011 г.). «Как на самом деле работает RAID 5». Проверено 23 марта 2017 г.

Внешние ссылки

На Викискладе есть средства массовой информации, связанные с Эксклюзивной дизъюнкцией.
Найдите эксклюзивный или или XOR в Wiktionary, бесплатный словарь.
  • Пример использования XOR в криптографии
  • Все о XOR
  • Доказательства свойств XOR и приложений XOR, CS103: Mathematical Foundations вычислительной техники, Стэнфордский университет

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

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