Разное

Исключающее или java: Логические операторы Java ( исключающее ИЛИ / логическое ИЛИ)

Содержание

Логические и побитовые операции в Java

  • Головна >
  • Каталог >
  • Java Стартовый >
  • Логические операции в Java

Для проходження тесту необхідно авторизуватися

Увійти Реєстрація

×

Ви відкрили доступ до тесту! Пройти тест

Для перегляду повної версії відеокурсу, онлайн тестування та отримання доступу до додаткових навчальних матеріалів придбайте курс Придбати курс

Для перегляду всіх відеокурсів ITVDN, представлених у Каталозі, а також для отримання доступу до навчальних матеріалів та онлайн тестування придбайте підписку Придбати підписку

№1

Введение в инфраструктуру Java

0:41:14

Матеріали урокуДомашні завданняТестування

Назначением данного урока является ознакомление с природой платформы Java, возможностями виртуальной машины Java (JVM), а также средствами разработки, которые применяются при построении Java-приложений на примере JetBrains IntelliJ IDEA. Выполняется обзор языков программирования и технологий, отличных от Java. На занятии рассматриваются простейшие примеры консольного приложения

Читати далі…

Машинная математика. Переменные и типы данных

1:04:19

Матеріали урокуДомашні завданняТестування

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

Читати далі…

Переменные и типы данных в Java

1:23:42

Матеріали урокуДомашні завданняТестування

В данном видео уроке Вы узнаете о назначение констант, основных арифметических операциях и операциях сравнения значений переменных. Демонстрируются примеры простого форматирования и вывода строк на экран.

Читати далі…

Условные конструкции Логические операции

0:48:34

Матеріали урокуДомашні завданняТестування

На уроке рассматривается работа операторов ветвления их назначение, использование основных условных конструкции: if-else, тернарного оператора и switch-case.

Читати далі…

Логические операции в Java

1:09:25

Матеріали урокуДомашні завданняТестування

Данный урок посвящен рассмотрению таких понятий, как логические и побитовые операции. На занятии объясняется применение и использование операций конъюнкции, дизъюнкции, исключающего «или», логических операторов, операторов сдвига. Рассматриваются короткозамкнутые вычисления и теорема Де Моргана.

Читати далі…

Циклические конструкции в Java

1:06:32

Матеріали урокуДомашні завданняТестування

На уроке рассматривается работа циклических операторов (while, do-while, for) и применение операторов break и continue. Объясняется работа циклов Дейкстры и использование цикла «Паук».

Читати далі…

Методы в Java

1:04:32

Матеріали урокуДомашні завданняТестування

Данный видео урок посвящен методам. В Java существуют 2 типа методов: методы с возвращаемым значением и методы без возвращаемого значения, а вот когда их использовать и зачем они существуют, Вы узнаете из этого урока.

Читати далі…

Методы и рекурсия в Java

0:55:10

Матеріали урокуДомашні завданняТестування

В данном видеоуроке поговорим о том, где Вам может пригодиться рекурсия, а также рассмотрим перегрузку методов.

Читати далі…

Массивы в Java

1:33:30

Матеріали урокуДомашні завданняТестування

На уроке рассматриваются примеры создания и использования массивов (одномерные, двумерные, трехмерные, зубчатые). Объясняются принципы получения и добавления данных в массивы.

Читати далі…

Наступний курс:

Java Базовый

ПОКАЗАТИ ВСЕ

основні теми, що розглядаються на уроці

0:01:02

Логические и побитовые операции

0:02:00

Конъюнкция

0:04:40

Побитовое И

0:10:10

Дизъюнкция

0:11:40

Побитовое ИЛИ

0:14:15

Исключающее ИЛИ

0:15:32

Побитовое «Исключающее ИЛИ»

0:17:45

Отрицание

0:18:59

Побитовое отрицание

0:20:14

Изменение знака

0:21:54

Побитовые логические операции

0:27:50

Робота с портами(конъюнкция и дизъюнкция)

0:32:14

Исключающее ИЛИ (пример использования)

0:36:30

Логические операции

0:46:03

Операции сдвига

1:02:15

Короткозамкнутые вычисления

1:06:09

Теоремы Де Моргана

ПОКАЗАТИ ВСЕ

ДЕТАЛЬНІШЕ

ДЕТАЛЬНІШЕ

ДЕТАЛЬНІШЕ

ДЕТАЛЬНІШЕ

ДЕТАЛЬНІШЕ

ДЕТАЛЬНІШЕ

Реєстрація через

або E-mail

Натиснувши на кнопку «Зареєструватися»,
Ви погоджуєтеся з умовами використання.

Вже є акаунт

Отримайте курс безкоштовно

Ви обрали курс для вивчення
«»
Щоб отримати доступ до курсу, зареєструйтеся на сайті.

РЕЄСТРАЦІЯ

Дякуємо за реєстрацію

Перейдіть на пошту та підтвердіть Ваш акаунт,
щоб отримати доступ до всіх
безкоштовних уроків та вебінарів на ITVDN.com

ПІДТВЕРДИТИ ПОШТУ РОЗПОЧАТИ НАВЧАННЯ

Дякуємо за реєстрацію

Ваш акаунт успішно підтверджено.
Почати навчання ви можете через Особистий кабінет
користувача або безпосередньо на сторінці курсу.

РОЗПОЧАТИ НАВЧАННЯ

Підтвердження акаунту

На Ваш номер телефону було надіслано смс із кодом активації акаунта. Введіть код у полі введення.

Надіслати код ще раз

Змінити номер телефону

Помилка

2.4. Операции языка Java

Основные арифметические операции сведены в табл. 2.2.

Таблица 2.2

Арифметические операции

Операция

Назначение

+

Сложение

Вычитание

*

Умножение

/

Деление

%

Получение остатка от деления

++

Инкремент

+=

Присваивание со сложением

-=

Присваивание с вычитанием

*=

Присваивание с умножением

/=

Присваивание с делением

%=

Присваивание с модулем

(остаток от деления)

Декремент

Кроме арифметических операций в языке Java определены битовые – поразрядные операции. =

Присваивание с исключающим ИЛИ

>>=

Присваивание с правым сдвигом

>>>=

Присваивание со сдвигом вправо, старший бит заполняется нулем

<<=

Присваивание со сдвигом влево

При составлении условий используются логические операции из табл. 2.4.

Таблица 2.4

Логические операции

Операция

Назначение

==

Сравнение

!=

Не равно

>

Больше

<

Меньше

>=

Больше, либо равно

<=

Меньше, либо равно

Результат логической операции – значение типа boolean.

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

Операции в выражениях выполняются в соответствии с определенным приоритетом (табл. 2.6).

Таблица 2.6

Приоритеты

Приоритет

Операции

1

++,—,~,!

2

*,/,%

3

+,-

4

>>,>>>,<<

5

>,>=,<,<=

6

==,!=

7

&

8

^

9

|

10

&&

11

||

Для изменения приоритета в выражениях используются круглые скобки. B !A false false false false false true true false true false true false false true true false true true true true true true false false

Сокращённые логические операторы

Кроме стандартных операторов AND (&) и OR (|) существуют сокращённые операторы && и ||.

Если взглянуть на таблицу, то видно, что результат выполнения оператора OR равен true, когда значение операнда A равно true, независимо от значения операнда B. Аналогично, результат выполнения оператора AND равен false, когда значение операнда A равно false, независимо от значения операнда B. Получается, что нам не нужно вычислять значение второго операнда, если результат можно определить уже по первому операнду. Это становится удобным в тех случаях, когда значение правого операнда зависит от значения левого.

Рассмотрим следующий пример. Допустим, мы ввели правило — кормить или не кормить кота в зависимости от числа пойманных мышек в неделю. Причём число мышек зависит от веса кота. Чем больше кот, тем больше он должен поймать мышей.

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

Теперь возьмём крайний случай. Кот обленился и не поймал ни одной мышки. Значение переменной mouse будет равно 0, а в выражении есть оператор деления. А делить на 0 нельзя и наша программа закроется с ошибкой. Казалось бы, мы предусмотрели вариант с 0, но Java вычисляет оба выражения mouse != 0 и weight / mouse < 1000, несмотря на то, что уже в первом выражении возвращается false.

Перепишем условие следующим образом (добавим всего лишь один символ):

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

Сокращённые варианты операторов AND и OR принято использовать в тех ситуациях, когда требуются операторы булевой логики, а их односимвольные родственники используются для побитовых операций.

Тернарный оператор

В языке Java есть также специальный тернарный условный оператор, которым можно заменить определённые типы операторов if-then-else — это оператор ?:

Тернарный оператор использует три операнда. Выражение записывается в следующей форме:

Если логическоеУсловие равно true, то вычисляется выражение1 и его результат становится результатом выполнения всего оператора. Если же логическоеУсловие равно false, то вычисляется выражение2, и его значение становится результатом работы оператора. Оба операнда выражение1 и выражение2 должны возвращать значение одинакового (или совместимого) типа.

Рассмотрим пример, в котором переменной absval присваивается абсолютное значение переменной val.

Переменной absval будет присвоено значение переменной val, если значение больше или равно нулю (вторая часть выражения). Если значение переменной val отрицательное, то переменной absval присваивается значение переменной, взятое со знаком минус, в результате минус на минус даст плюс, то есть положительно значение. Перепишем код с использованием if-else:

Существуют четыре логических оператора — &, &&, | и ||.

Если оба операнда имеют значение true, тогда операторы & и && возвращают true.

Если хотя бы один операнд имеет значение true, тогда операторы | и || возвращают true.

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

Примечание: || и && могут быть использованы только в логических выражениях.

Без логических операций никуда не деться, и в курсе JavaRush они появляются с первых уровней, вместе с условиями и типом данных boolean. Пользоваться методами математической логики программисты приучаются постепенно. Для более уверенных манипуляций с логическими конструкциями требуется определённая сноровка и понимание некоторых процессов. Так что подробнее и уже на совсем другом уровне к этим операциям подходят в конце квеста Multithreading, когда большинство студентов уже не слишком отвлекается непосредственно на синтаксис и конструкции, а старается вникать в суть задачи.

Оператор логического отрицания !

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

Значение a !a
false true
true false

Пример. Операция логического отрицания Вывод программы будет следующий:

Логическое И — &, а также условное И — &&

Логическое И или конъюнкцию применяют к двум выражениям, и результат его действия будет истинным (true) только если оба операнда истинны. То есть, если один из операндов a или b равен false, то выражение a & b будет false независимо от значения второго оператора. Если представить, что true — это число 1, а false — 0, то оператор & работает точно так же, как обычное умножение. Поэтому логическое И часто называют “логическим умножением”. И, кстати, этот факт помогает быстрее запомнить работу оператора & и не путать его с оператором логического или | . Таблица истинности И, она же — результат работы оператора &

a b a & b
true true true
true false false
false true false
false false false

Логическое И, оно же — конъюнкция, примеры: Результат работы программы: Оператор && иногда называют “сокращённым И”. Он выдаёт такой же результат при работе с логическими операндами, что и оператор & . Однако есть разница в самой его работе. Так, вы уже успели заметить, что если в выражении ( a & b ) операнд a равен false, то не имеет смысла проверять значение операнда b : результат операции точно будет false. Так что если нам принципиально не нужно значение второго операнда, с помощью && мы сокращаем количество вычислений в программе. Если мы заменим в примере все операторы & на && , результат работы будет точно таким же, но сама программа будет работать чуточку быстрее (правда, мы этого не заметим, так как речь идёт о мили-микро… короче говоря, об очень маленьких единицах времени).

Логическое ИЛИ — оператор |, а также условное ИЛИ — оператор ||

Оператор ИЛИ в Java обозначается символом | . Логическое ИЛИ или дизъюнкцию применяют к двум выражениям, и результат его действия будет ложным (false) тогда и только тогда, когда оба операнда ложны. Здесь мы в какой-то мере наблюдаем ту же картину, что и в случае с оператором & , но с точностью до наоборот. То есть, если хотя бы один операнд равен true, то выражение a | b гарантированно будет true независимо от значения второго оператора. Если & ведёт себя как логическое умножение, то ИЛИ — это логическое сложение, если представить, что true — это 1, а false — 0. Только следует помнить, что логическое сложение работает не так, как обычное. 1 + 1 в данном случае равно не 2, а 1 (числа 2 в этой системе просто не существует). Иногда дизъюнкцию понимают как максимум из 0 и 1, и в таком случае если хотя бы один операнд равен 1 (true), мы получим именно true. Таблица истинности ИЛИ, она же — результат работы оператора | :

a b a | b
true true true
true false true
false true true
false false false

Логическое ИЛИ, оно же — дизъюнкция, пример: Результат: Если мы применим оператор условного ИЛИ — || вместо | , мы получим ровно тот же результат, но, как и в случае с условным И && , он будет действовать экономно: если мы “нарываемся” на первый операнд равный true, значение второго операнда не проверяется, а сразу выдаётся результат true.

Записываем число -13 в так называемом “прямом коде”. Для этого меняем старший разряд числа на 1.
Результат действия:

Далее инвертируем все разряды (меняем 0 на 1, а 1 на 0) кроме знакового разряда. Его, по сути, мы уже поменяли.
Результат действия:

(да, шаги 1 и 2 можно было бы совместить, но лучше представлять именно так)

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

13 просто изменит значение каждого бита на противоположное. В результате мы получим: Или 12 в десятичном виде.

возьмем простой пример объекта Cat . Я хочу быть уверен, что» not null» cat является оранжевым или серым.

Я верю и приходит первым, затем OR. Я немного нечеткий, так что вот мои вопросы:

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

кроме того, что произойдет, если я добавлю круглые скобки; это изменит порядок операции?

изменится ли мой порядок операций с языка на язык?

6 ответов

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

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

логический порядок операций (на всех языках, я считаю):

  1. parens
  2. не
  3. и
  4. или

таким образом, ваша логика выше эквивалентна:

выражение в основном идентично:

порядок приоритета здесь таков и ( && ) имеет более высокий приоритет, чем OR ( || ).

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

ie использует equals() методы String сравнение, а не == который просто ссылается на равенство. Ссылочное равенство для строк может вводить в заблуждение. Например:

во-первых, ваш оператор if содержит три основных выражения:

  1. кошка != null
  2. кошка.getColor () = = «оранжевый»
  3. кошка.getColor () = = «серый»

первое выражение просто проверяет, не является ли cat нулевым. Его необходимо, в противном случае второе выражение будет выполняться и приведет к NPE(null pointer excpetion) . Вот почему использование && между первым и вторым выражением. Когда вы используете && , Если первое выражение значение false, то второе выражение не выполняется. Наконец, вы проверяете, является ли цвет кошки серым.

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

правильный способ сделать это:

Проверьте порядок скобок.

да && определенно оценивается до || . (Побитовое исключающее или) (Azure Stream Analytics) — Stream Analytics Query

Twitter LinkedIn Facebook Адрес электронной почты

  • Статья
  • Чтение занимает 2 мин

Выполняет операцию побитового логического исключающего или (XOR) между двумя целочисленными значениями, оценивая каждый из них в обоих выражениях. bigint0) AS XORtype_mixed INTO typesXOR FROM MyCTE

Возвращает:

XORtype_bit XORtype_bigint ORtype_mixed
bit BIGINT BIGINT

См. также

  • Битовые операторы (Azure Stream Analytics)
  • & (Побитовое и) (Azure Stream Analytics)
  • | (Побитовое или) (Azure Stream Analytics)
  • ~ (Побитовое не) (Azure Stream Analytics)
  • Общие сведения о типах данных (Azure Stream Analytics)
  • Функции преобразования (Azure Stream Analytics)
  • Встроенные функции (Azure Stream Analytics)

Руководство по Java Core. Базовые операторы. – PROSELYTE

Для манипулирования переменными в языке Java предусмотренно множество операторов. Все операторы мы модем поделить на такие группы:

  • Арифметические операторы
  • Операторы сравнения
  • Битовые операторы
  • Логические операторы
  • Операторы присваивания
  • Другие

Рассмотрим эти группы отдельно.


Арифметические операторы

Этот тип операторов используется для математических операций.

Представим, что у нас есть две целочисленные переменные (int) A = 50, B = 20.

Примеры:

+ (Сложение)  A + B = 70
– (Вычитание) A – B = 30
* (Умножение) A * B = 1000
/ (Деление) A / B = 2
% (Остаток от деления) A % B = 10
++ (Инкремент) A++ = 51
— (Декремент) B– = 19

Операторы сравнения

Результатом оператора сравнения является логический тип boolean, который говорит нам, является ли данное утверждение правдой (true) или ложью (false).

Представим, что у нас есть две целочисленные переменные (int) A = 50, B = 20.

Примеры:

== (Равен)  (A == B) -> false
!= (Не равен) (A != B) -> true
> (Больше, чем) (A > B) -> true
< (Меньше, чем) (A < B) -> false
>= (Больше, чем или равно) (A >= B) -> true
<= (Меньше, чем или равно) (A <= B) -> false

Битовые операторы

В языке Java существует ряд битовых операторов, которые поддерживают целочисленные типы данных.

Битовые операторы позволяют нам выполнять побитовые операции.

Представим, что у нас есть две целочисленные переменные (int) A = 50, B = 20.

B) -> 0010 0110 ~ (Побитовое дополнение) ( ~A ) -> 1100 1101
<< (Побитовый сдвиг влево) (A << 1) -> 100 (0110 0100)
>> (Побитовый сдвиг вправо) (B >> 2) -> 5 (0000 0101)
>>> (Побитовый сдвиг вправо с присвоением)
( A >>> 3) -> 6 (0000 0110)

Логические операторы

В языке Java поддерживаются 3 логических оператора, все они приведены таблице ниже.

Представим, что у нас есть две логические переменные (boolean) T = true и F = false.

&& (Логическое ‘И’)
    (A && B) -> false
|| (Логическое ‘ИЛИ’)    (A || B) -> true
! (Логическое ‘НЕ’)
   !(A || B) -> false

Операторы присваивания

В языке Java есть 11 операторов присваивания. Рассмотрим их на примерах.

Представим, что у нас есть две целочисленные переменные (int) A = 50, B = 20 и некая переменная С, значение которой, пока не присвоено.

=
   С = A + B ( C == 70 )
+=    A += B (A == 70)
-=
   A -= B (A == 30)
*=    B *= A (B == 1000)
/=    A /= B (A == 2)
%=
   A %= B (A == 10)
<<=
   B <<= 2 (B == 80)
>>=
   A >>= 2 (A == 12)
&=    B &= 2 (B = B & 2 )
^=
   A ^= 2 (A == 48)
|=    A |= 3 (A == 51)

Другие

К другим операторам в языке Java относится только 1. Это тернарный оператор ветвления IF.

Более подробно мы рассмотрим IF далее, а пока приведём общую форму записи:

Допустим у нас есть логическая переменная (boolean) isActive, значение которой нам неизвестно.

Пример:

int a = (isActive) ? 100 : 200.

Разъяснение:

Если isActive = true, тогда a = 100.

Если isActive = false, тогда a = 200.


В этом уроке мы рассмотрели операторы для манипулирования переменными в языке Java.

Более подробно с операторами в языке Java можно ознакомиться в спецификации языка Java (Java Language Specification).

В следующем уроке мы рассмотрим массивы в языке Java и их виды.

Таблица истинности java — ПК журнал

Рейтинг статьи

Загрузка…

Логические операторы

Логические операторы языка Java выполняются только с операндами типа boolean .

Следующая таблица перечисляет логические операторы языка Java:

ОперацияОписание
&Логическая операция И (AND) или конъюнкция
|Логическая операция ИЛИ (OR) или дизъюнкция
^Логическая операция исключающее ИЛИ (XOR)
!Логическая унарная операция НЕ (NOT)
||Укороченная логическая операция ИЛИ (short-circuit)
&&Укороченная логическая операция И (short-circuit)
==Равенство
!=Неравенство
&=Логическая операция И с присваиванием
|=Логическая операция ИЛИ с присваиванием
^=Логическая операция исключающее ИЛИ с присваиванием

1.

) — результат будет true , только если или A равно true , или В равно true . Пример: у двух друзей на двоих один велосипед, поездка на велосипеде состоится только если один из них поедет на нем. Вдвоем они ехать не могут.

NOT (!) — инвертирование значения. Если значение было true, то станет false , и наоборот.

Рассмотрим пример использования логических операторов:

2. Укороченные логические операторы (short-circuit).

Чаще всего в языке Java используются так называемые укороченные логические операторы (short-circuit):

Правый операнд сокращенных операций вычисляется только в том случае, если от него зависит результат операции, то есть если левый операнд конъюнкции имеет значение true , или левый операнд дизъюнкции имеет значение false .

В формальной спецификации языка Java укороченные логические операции называются условными.

В следующем примере правый операнд логического выражения вычисляться не будет, так как условие d!=0 не выполняется и нет смысла дальше вычислять это выражение:

Если же логическое выражение переписать как d != 0 & num / d > 10 , то правое выражение вычисляться будет. И в этом случае программа выбросит исключение времени выполнения с сообщением — на ноль делить нельзя.

Если нам надо сравнить возможный диапазон значений для какой-то переменной, например — a такое условие разбивается на два: a :

3. Операции ==, !=.

Здесь все просто — чтобы сравнить два значения типа boolean , можно использовать знаки == (проверка на равенство) и != (проверка на неравенство):

4. Операции с присваиванием.

Также существуют операции с присваиванием для AND, OR, XOR. Посмотрим пример:

Логические операторы

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

Таблица логических операторов в Java

ОператорОписание
&Логическое AND (И)
&&Сокращённое AND
|Логическое OR (ИЛИ)
||Сокращённое OR
^Логическое XOR (исключающее OR (ИЛИ))
!Логическое унарное NOT (НЕ)
&=AND с присваиванием
|=OR с присваиванием
^=XOR с присваиванием
==Равно
!=Не равно
?:Тернарный (троичный) условный оператор

Логические операторы &, |, ^ действуют применительно к значениям типа boolean точно так же, как и по отношению к битам целочисленных значений. B!Afalsefalsefalsefalsefalsetruetruefalsetruefalsetruefalsefalsetruetruefalsetruetruetruetruetruetruefalsefalse

Сокращённые логические операторы

Кроме стандартных операторов AND (&) и OR (|) существуют сокращённые операторы && и ||.

Если взглянуть на таблицу, то видно, что результат выполнения оператора OR равен true, когда значение операнда A равно true, независимо от значения операнда B. Аналогично, результат выполнения оператора AND равен false, когда значение операнда A равно false, независимо от значения операнда B. Получается, что нам не нужно вычислять значение второго операнда, если результат можно определить уже по первому операнду. Это становится удобным в тех случаях, когда значение правого операнда зависит от значения левого.

Рассмотрим следующий пример. Допустим, мы ввели правило — кормить или не кормить кота в зависимости от числа пойманных мышек в неделю. Причём число мышек зависит от веса кота. Чем больше кот, тем больше он должен поймать мышей.

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

Теперь возьмём крайний случай. Кот обленился и не поймал ни одной мышки. Значение переменной mouse будет равно 0, а в выражении есть оператор деления. А делить на 0 нельзя и наша программа закроется с ошибкой. Казалось бы, мы предусмотрели вариант с 0, но Java вычисляет оба выражения mouse != 0 и weight / mouse Реклама

9.

Java — Основные операторы языка

Java предоставляет богатый набор операторов для управления переменными. Все операторы Java можно разделить на следующие группы:

  • арифметические операторы;
  • операторы сравнения;
  • побитовые операторы;
  • логические операторы;
  • операторы присваивания;
  • прочие операторы.

Содержание

Арифметические операторы

Арифметические операторы — используются в математических выражениях таким же образом, как они используются в алгебре. Предположим, целая переменная A равна 10, а переменная B равна 20. В следующей таблице перечислены арифметические операторы в Java:

ОператорОписаниеПример
+Складывает значения по обе стороны от оператораA + B даст 30
Вычитает правый операнд из левого операндаA — B даст -10
*Умножает значения по обе стороны от оператораA * B даст 200
/Оператор деления делит левый операнд на правый операндB / A даст 2
%Делит левый операнд на правый операнд и возвращает остатокB % A даст 0
++Инкремент — увеличивает значение операнда на 1B++ даст 21
Декремент — уменьшает значение операнда на 1B— даст 19

Пример

Следующий простой пример показывает программно арифметические операторы. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:

Это произведет следующий результат:

Операторы сравнения

Есть следующие операторы сравнения, поддерживаемые на языке Java. Предположим, переменная A равна 10, а переменная B равна 20. В следующей таблице перечислены реляционные операторы или операторы сравнения в Java:

ОператорОписаниеПример
==Проверяет, равны или нет значения двух операндов, если да, то условие становится истинным(A == B) — не верны
!=Проверяет, равны или нет значения двух операндов, если значения не равны, то условие становится истинным(A != B) — значение истинна
>Проверяет, является ли значение левого операнда больше, чем значение правого операнда, если да, то условие становится истинным(A > B) — не верны
=Проверяет, является ли значение левого операнда больше или равно значению правого операнда, если да, то условие становится истинным(A >= B) — значение не верны
> (сдвиг вправо)Бинарный оператор сдвига вправо. Значение правых операндов перемещается вправо на количество бит, заданных левых операндом.A >> 2 даст 15, который является 1111
>>> (нулевой сдвиг вправо)Нулевой оператор сдвига вправо. Значение левых операндов перемещается вправо на количество бит, заданных правым операндом, а сдвинутые значения заполняются нулями.A >>> 2 даст 15, который является 0000 1111

Пример

Следующий простой пример показывает, программно побитовые операторы в Java. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:

Будет получен следующий результат:

Логические операторы

Предположим, логическая переменная A имеет значение true, а переменная B хранит false. В следующей таблице перечислены логические операторы в Java:

ОператорОписаниеПример
&&Называется логический оператор «И». Если оба операнда являются не равны нулю, то условие становится истинным(A && B) — значение false
||Называется логический оператор «ИЛИ». Если любой из двух операндов не равен нулю, то условие становится истинным(A || B) — значение true
!Называется логический оператор «НЕ». Использование меняет логическое состояние своего операнда. Если условие имеет значение true, то оператор логического «НЕ» будет делать false!(A && B) — значение true

Пример

Следующий простой пример показывает, программно логические операторы в Java. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:

Это произведет следующий результат:

Операторы присваивания

Существуют следующие операторы присваивания, поддерживаемые языком Java:

ОператорОписаниеПример
=Простой оператор присваивания, присваивает значения из правой стороны операндов к левому операндуC = A + B, присвоит значение A + B в C
+=Оператор присваивания «Добавления», он присваивает левому операнду значения правогоC += A, эквивалентно C = C + A
-=Оператор присваивания «Вычитания», он вычитает из правого операнда левый операндC -= A, эквивалентно C = C — A
*=Оператор присваивания «Умножение», он умножает правый операнд на левый операндC * = A эквивалентно C = C * A
/=Оператор присваивания «Деление», он делит левый операнд на правый операндC /= A эквивалентно C = C / A
%=Оператор присваивания «Модуль», он принимает модуль, с помощью двух операндов и присваивает его результат левому операндуC %= A, эквивалентно C = C % A
>=Оператор присваивания «Сдвиг вправо»C >>= 2, это как C = C >> 2
&=Оператор присваивания побитового «И» («AND»)C &= 2, это как C = C & 2
^=Оператор присваивания побитового исключающего «ИЛИ» («XOR»)C ^= 2, это как C = C ^ 2
|=Оператор присваивания побитового «ИЛИ» («OR»)C |= 2, это как C = C | 2

Пример

Следующий простой пример показывает, программно логические операторы в Java. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:

Будет получен следующий результат:

Прочие операторы

Есть несколько других операторов, поддерживаемых языком Java.

Тернарный оператор или условный оператор (?:)

Тернарный оператор — оператор, который состоит из трех операндов и используется для оценки выражений типа boolean. Тернарный оператор в Java также известен как условный оператор. Этот. Цель тернарного оператора или условного оператора заключается в том, чтобы решить, какое значение должно быть присвоено переменной. Оператор записывается в виде:

Пример

Ниже приведен пример:

Будет получен следующий результат:

Оператор instanceof

Оператор instanceof — проверяет, является ли объект определенного типа (типа класса или типа интерфейса) и используется только для переменных ссылочного объекта. Оператор instanceof записывается в виде:

Примеры

Если переменная ссылочного объекта в левой части оператора проходит проверку для класса/типа интерфейса на правой стороне, результатом будет значение true. Ниже приведен пример и описание оператора instanceof:

Будет получен следующий результат:

Этот оператор по-прежнему будет возвращать значение true, если сравниваемый объект является совместимым с типом на право назначения. Ниже приводится еще один пример:

Будет получен следующий результат:

Приоритет операторов в Java

Приоритет операторов определяет группирование терминов в выражении. Это влияет как вычисляется выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например оператор умножения имеет более высокий приоритет, чем оператор сложения:

Например, x = 7 + 3 * 2. Здесь x присваивается значение 13, не 20, потому что оператор «*» имеет более высокий приоритет, чем «+», так что сначала перемножается «3 * 2», а затем добавляется «7».

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

Операторы Java

В этой статье вы узнаете о различных типах операторов Java и их синтаксисе.

Операторы это специальные символы, которые осуществляют операции над операндами ( переменными и значениями ). Например, « + » это оператор, который производит сложение.

Сейчас вы узнаете, как использовать операторы, чтобы манипулировать переменными.

Операторы присваивания

Используются в Java , чтобы присвоить значения переменным. Например,

Оператор « = » присваивает значение справа от себя переменной, находящейся слева. В примере переменной age присвоено значение 5 .

Пример 1: оператор присваивания

Когда вы запустите программу, на экран выведется:

Арифметические операторы

Арифметические операторы Java используются, чтобы производить математические операции сложения, вычитания умножения и так далее.

ОператорЗначение
+Сложение (также используется для конкатенации строк)
Вычитание
*Умножение
/Деление
%Остаток от деления

Пример 2: Арифметические операторы

Когда вы запустите программу, на экран выведется:

В примере с оператором деления Java , приведенном выше, использованные операнды – переменные. Кроме этого могут использоваться символьные значения. Например:

Оператор « + » также может быть использован, чтобы соединить ( конкатенировать ) две строки или больше.

Пример 3: Арифметический оператор

Когда вы запустите программу, на экран выведется:

Унарные операторы

Унарный оператор Java производит операцию только над одним операндом.

ОператорЗначение
+Унарный плюс (не нужен, так как числа положительные и без него).
Унарный минус; инвертирует знак выражения.
++Оператор инкремента; увеличивает значение на 1.
Оператор декремента; уменьшает значение на 1.
!Оператор логического отрицания; инвертирует значение булевой переменной.

Пример 4: Унарный оператор

Когда вы запустите программу, на экран выведется:

В Java можно использовать операторы « ++ » и « — » в качестве префикса и постфикса. Оператор « ++ » увеличивает значение на 1 , а « — » уменьшает значение на 1 .

Есть большая разница в использовании операторов Java инкремента и декремента в префиксе и в постфиксе. Рассмотрим пример:

Пример 5: Унарный оператор

Когда вы запустите программу, на экран выведется:

Когда выполняется выражение System.out.println(number++) , первым вычисляется изначальное значение. Переменная number увеличивается только после этого. Поэтому вы получите на выходе 5.2 . Далее, когда выполняется System.out.println(number) , показывается значение 6.2 .

Тем не менее, когда выполняется System.out.println(++number) , number увеличивается на 1 перед тем, как будет выведено на экран. Так же обстоят дела и с оператором Java декремента.

Операторы равенства и отношений

Операторы равенства и отношений проверяют, является ли операнд больше, меньше, равен, неравен второму и так далее. Получаемый результат равен true или false .

ОператорОписаниеПример
==равен5 == 3 результат false
!=неравен5 != 3 результат true
>Больше5 > 3 результат true
=Больше или равен5 >= 5 результат true
Java , на экран выведется:

Здесь мы использовали оператор « > », чтобы проверить, больше ли number1 , чем number2 .

Так как number2 больше, чем number1 , результатом выражения number1 > number2 будет false .

Кроме операторов отношений, есть оператор сравнения типов instanceof , который сравнивает объект и определенный тип.

Оператор instanceof

Пример оператора instanceof .

Когда вы запустите программу, на экран выведется true . Это происходит от того, что test — экземпляр класса String .

Логические операторы

Java логические операторы || ( условное-ИЛИ (OR) ) и && ( условное-И (AND) ) совершают операции над булевыми выражениями. Вот как они работают.

ОператорОписаниеПример
||условное-ИЛИ; true если хотя бы одно из булевых выражений истинно (true)false || true результат — true
&&условное-И; истинно если все булевы выражения истинны (true).false && true результат — false

Пример 8: Логические операторы

Когда вы запустите программу, на экран выведется:

Тернарный оператор

Условный оператор или тернарный оператор Java « ? :» — это сокращение выражения if-then-else . 5|=x |= 5x = x | 5

Данная публикация представляет собой перевод статьи « Java Operators » , подготовленной дружной командой проекта Интернет-технологии.ру

Оценка статьи:

Загрузка…

Adblock
detector

) не учитывается при когнитивной сложности — IntelliJ Platform

Cargonat (Тобиас Думмшат)

#1

  • Плагин SonarLint в IntelliJ (версия плагина 4.10.0.19739)
  • Напишите метод с достаточно высокой когнитивной сложностью, чтобы вызвать проблему
  • Для меня следующий пример делает трюк с 20 когнитивной сложностью 9’не выделено из-за сложности с = «исключающее»; if (a && b) // ‘&&’ выделено для сложности с = «и»; если (а || б)// ‘||’ выделены для сложности с = «или»; // быстро увеличить когнитивную сложность с помощью вложенных операторов if если правда){ если правда){ если правда){ если правда){ если правда){ } } } } } возврат с; }

    alban. auzeill (Альбан Озейл)

    Использование здесь оператора != создает вложенные равенства, которые кажутся мне более сложными. Я также не считаю != логическим оператором.

    Что касается когнитивной сложности, я чувствую, что любая логическая операция немного увеличивает ее.

    С наилучшими пожеланиями
    Тобиас

    alban.auzeill (Альбан Озейл)

    #4 9б | c & d) { // Несоответствие \o/ вернуть 42; } вернуть 0; }

    Каргонат (Тобиас Думмшат)

    #5

    Привет, Албан

    Я не думаю, что расширение RSPEC-2178 — правильный выбор. Это правило касается короткого замыкания, которое здесь не применяется.

    Кажется, нет технических преимуществ в использовании 9 . Единственная разница, по-видимому, заключается в личных предпочтениях и личной легкости понимания, как видно из комментариев к ответам здесь.

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

    С наилучшими пожеланиями,
    Тобиас

    alban.auzeill (Альбан Озейл)

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

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

    • +1 для и и | использует ту же логику, что и && 9 и !=

    Каргонат (Тобиас Думмшат)

    #9

    Привет, Албан,

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

    С наилучшими пожеланиями
    Тоби

    alban. auzeill (Альбан Озейл) 9 , != и == , когда хотя бы один операнд также является двоичным выражением (комбинация двоичных выражений)

система (система) закрыто

#11

Эта тема была автоматически закрыта через 7 дней после последнего ответа. Новые ответы больше не допускаются.

Операторы

8.1. Оператор спреда

Оператор Spread-dot ( *. ), часто сокращенно просто Оператор Spread, используется для вызова действия над всеми элементами агрегатного объекта. Это эквивалентно вызову действия над каждым элементом и сбору результата в список:

 class Car {
    Строка сделать
    Струнная модель
}
деф автомобили = [
       новый автомобиль(марка: "Пежо", модель: "508"),
       новый автомобиль(марка: 'Renault', модель: 'Clio')]   (1) 
def makes = автомобили*. make   (2) 
assert makes == ['Peugeot', 'Renault']   (3)  
1 создайте список из автомобилей элементов. Список представляет собой совокупность объектов.
2 вызвать оператора спреда из списка, обратившись к свойству make каждого элемента
3 возвращает список строк, соответствующих набору из сделать штук

Выражение cars*.make эквивалентно cars.collect{ it.make } . Нотация Groovy GPath позволяет сократить путь, когда указанное свойство не является свойством содержащего списка, в этом случае он автоматически распространять. В ранее упомянутом случае выражение cars.make может можно использовать, хотя часто рекомендуется сохранять явный оператор с расставленными точками.

Оператор распространения является нулевым, что означает, что если элемент коллекции имеет значение null, он вернет ноль вместо того, чтобы выбросить NullPointerException :

 автомобилей = [
   новый автомобиль(марка: "Пежо", модель: "508"),
   ноль,   (1) 
   новый автомобиль(марка: 'Renault', модель: 'Clio')]
утверждать cars*.make == ['Peugeot', null, 'Renault']   (2) 
утверждать null*.make == null   (3)  
1 построить список, для которого один из элементов равен ноль
2 с использованием оператора распространения вызовет
, а не
исключение NullPointerException
3 получатель также может иметь значение null, и в этом случае возвращаемое значение равно null

Оператор распространения можно использовать в любом классе, реализующем интерфейс Iterable :

 class Component {
    Длинный идентификатор
    Имя строки
}
класс CompositeObject реализует Iterable {
    Компоненты защиты = [
        новый компонент (id: 1, имя: «Foo»),
        новый компонент (id: 2, имя: «Бар»)]

    @Override
    Итератор<Компонент> итератор() {
        компоненты. iterator()
    }
}
def составной = новый составной объект ()
утверждать составной*.id == [1,2]
утверждать составное*.имя == ['Foo','Bar'] 

Использовать несколько вызовов оператора растровой точки (здесь cars*.models*.name ), когда работа с агрегатами структур данных, которые сами содержат агрегаты:

 class Make {
    Имя строки
    Список моделей
}

@канонический
модель класса {
    Имя строки
}

деф автомобили = [
    новая марка (название: «Пежо»,
             модели: [новая модель('408'), новая модель('508')]),
    новый Марка (название: «Рено»,
             модели: [новая модель('Clio'), новая модель('Captur')])
]

def makes = автомобили*.название
assert делает == ['Peugeot', 'Renault']

def модели = автомобили*.модели*.название
утверждать модели == [['408', '508'], ['Clio', 'Captur']]
assert models.sum() == ['408', '508', 'Clio', 'Captur'] // выравнивание на один уровень
assert models.flatten() == ['408', '508', 'Clio', 'Captur'] // выравниваем все уровни (в данном случае один) 

Рассмотрите возможность использования метода collectNested

DGM вместо оператора с расставленными точками для коллекций коллекций:

 class Car {
    Строка сделать
    Струнная модель
}
деф автомобили = [
   [
       новый автомобиль(марка: 'Peugeot', модель: '408'),
       новый автомобиль(марка: 'Peugeot', модель: '508')
   ], [
       новый автомобиль(марка: 'Renault', модель: 'Clio'),
       новый автомобиль(марка: 'Renault', модель: 'Captur')
   ]
]
def models = cars. collectNested{ it.model }
утверждать модели == [['408', '508'], ['Clio', 'Captur']] 
8.1.1. Распространение аргументов метода

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

 int function (int x, int y, int z) {
    х*у+г
} 

тогда, если у вас есть следующий список:

 def args = [4,5,6] 

вы можете вызвать метод без определения промежуточных переменных:

 assert function(*args) == 26 

Можно даже смешивать обычные аргументы с расширенными:

 args = [4]
функция утверждения(*args,5,6) == 26 
8.1.2. Элементы списка распространения

При использовании внутри литерала списка оператор расширения действует так, как если бы содержимое элемента расширения было встроено в список:

 def items = [4,5]   (1) 
список по умолчанию = [1,2,3,*элементы,6]   (2) 
список утверждений == [1,2,3,4,5,6]   (3)  
1 предметов это список
2 мы хотим вставить содержимое списка элементов непосредственно в список без вызова addAll
3 содержимое элементов было встроено в список
8.
1.3. Элементы карты распространения

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

 def m1 = [c:3, d:4]   (1) 
карта защиты = [a:1, b:2, *:m1]   (2) 
утверждать карту == [a:1, b:2, c:3, d:4]   (3)  
1 m1 — это карта, которую мы хотим встроить
2 мы используем нотацию *:m1 для распространения содержимого m1 на карту
3 карта содержит все элементы m1

Должность оператора карты спреда имеет значение, как показано в следующем примере:

 по умолчанию m1 = [c:3, d:4]   (1) 
карта защиты = [a:1, b:2, *:m1, d: 8]   (2) 
assert map == [a:1, b:2, c:3, d:8]   (3)  
1 m1 — это карта, которую мы хотим встроить
2 мы используем нотацию *:m1 для распространения содержимого m1 на карту , но переопределить ключ d после распространяя
3 карта содержит все ожидаемые ключи, но d был переопределен

8.

2. Оператор диапазона

Groovy поддерживает концепцию диапазонов и предоставляет нотацию ( .. ) для создания диапазонов объектов:

 def range = 0..5   (1) 
утверждать (0..5).collect() == [0, 1, 2, 3, 4, 5]   (2) 
утверждать (0..<5).collect() == [0, 1, 2, 3, 4]   (3) 
утверждать (0<..5).collect() == [1, 2, 3, 4, 5]   (4) 
утверждать (0<..<5).collect() == [1, 2, 3, 4]   (5) 
assert (0..5) instanceof List   (6) 
утверждать (0..5).size() == 6   (7)  
1 простой диапазон целых чисел, сохраненный в локальной переменной
2 и IntRange с включенными границами
3 и IntRange , с исключительной верхней границей
4 и IntRange с эксклюзивной нижней границей
5 и IntRange , с исключительными нижними и верхними границами
6 a groovy. lang.Range реализует интерфейс List
7 означает, что вы можете вызвать на нем метод размера

Реализация диапазонов упрощена, что означает, что сохраняются только нижняя и верхняя границы. Вы можете создать диапазон из любых Сопоставимый объект, который имеет методов next() и previous() для определения следующего/предыдущего элемента в диапазоне. Например, вы можете создать диапазон символов следующим образом:

 assert('a'..'d').collect() == ['a','b','c','d'] 

8.3. Оператор космического корабля

Оператор космического корабля ( <=> ) делегирует метод compareTo :

 assert (1 <=> 1) == 0
утверждать (1 <=> 2) == -1
утверждать (2 <=> 1) == 1
утверждать ('a' <=> 'z') == -1 

8.4. Оператор нижнего индекса

Оператор нижнего индекса представляет собой сокращенную запись для getAt или putAt , в зависимости от того, найдете ли вы его на левая или правая часть задания:

 def list = [0,1,2,3,4]
утвердить список [2] == 2   (1) 
список[2] = 4   (2) 
утвердить список[0. .2] == [0,1,4]   (3) 
список[0..2] = [6,6,6]   (4) 
список утверждений == [6,6,6,3,4]   (5)  
1 [2] можно использовать вместо getAt(2)
2 , если слева от задания, вызовет putAt
3 getAt также поддерживает диапазоны
4 так же как и putAt
5 список изменен

Оператор нижнего индекса в сочетании с пользовательской реализацией getAt / putAt является удобным способом деструктурирования объекты:

 класс пользователя {
    Длинный идентификатор
    Имя строки
    защита getAt(int i) {   (1) 
        переключатель (я) {
            случай 0: возвращаемый идентификатор
            случай 1: вернуть имя
        }
        выбросить новое исключение IllegalArgumentException("Нет такого элемента $i")
    }
    void putAt (int i, значение по умолчанию) {   (2) 
        переключатель (я) {
            случай 0: идентификатор = значение; возвращаться
            случай 1: имя = значение; возвращаться
        }
        выбросить новое исключение IllegalArgumentException("Нет такого элемента $i")
    }
}
def user = новый пользователь (id: 1, имя: «Алекс»)   (3) 
утверждать пользователя [0] == 1   (4) 
утвердить пользователя [1] == 'Алекс'   (5) 
пользователь [1] = 'Боб'   (6) 
утверждать user. name == 'Боб'   (7)  
1 класс User определяет пользовательский getAt реализация
2 класс User определяет пользовательскую реализацию putAt
3 создать образец пользователя
4 с помощью оператора индекса с индексом 0 позволяет получить идентификатор пользователя
5 с помощью оператора нижнего индекса с индексом 1 позволяет получить имя пользователя
6 мы можем использовать оператор нижнего индекса для записи в свойство благодаря делегированию putAt
7 и проверьте, действительно ли это свойство имя было изменено

8.

5. Оператор безопасного индексирования

Groovy 3.0.0 представляет оператор безопасного индексирования, т. е. ?[] , что аналогично ?. . Например:

 Строка[] массив = ['a', 'b']
assert 'b' == array?[1] // получаем с использованием индекса обычного массива
array?[1] = 'c' // устанавливаем с использованием индекса обычного массива
утверждать 'c' == массив?[1]

массив = ноль
assert null == array?[1] // возвращаем null для всех значений индекса
array?[1] = 'c' // тихо игнорируем попытку установить значение
утверждать массив null ==?[1]

def personInfo = [имя: 'Daniel.Sun', местоположение: 'Шанхай']
assert 'Daniel.Sun' == personInfo?['name'] // используем индекс карты нормалей
personInfo?['name'] = 'sunlan' // устанавливается с использованием индекса карты нормалей
утверждать 'sunlan' == personInfo?['name']

информация о человеке = ноль
assert null == personInfo?['name'] // возвращаем null для всех значений карты
personInfo?['name'] = 'sunlan' // незаметно игнорируем попытку установить значение
утверждать null == personInfo?['name'] 

8.

6. Оператор принадлежности

Оператор принадлежности ( в ) эквивалентен вызову метода isCase . В контексте списка это эквивалентно для вызова содержится , как в следующем примере:

 def list = ['Grace','Rob','Emmy']
утверждать («Эмми» в списке)   (1)  
1 эквивалентно вызову list.contains('Эмми') или list.isCase('Эмми')

8.7. Оператор идентификации

В Groovy использование == для проверки равенства отличается от использования того же оператора в Java. В Groovy вызов равен . Если вы хотите сравнить ссылочное равенство, вы должны использовать равно , как в следующем примере:

 def list1 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']   (1) 
def list2 = ['Groovy 1. 8','Groovy 2.0','Groovy 2.3']   (2) 
утверждать список1 == список2   (3) 
утверждать !list1.is(list2)   (4)  
1 Создать список строк
2 Создайте еще один список строк, содержащих те же элементы
3 используя == , мы проверяем равенство объектов
4 , но использование равно , мы можем проверить, что ссылки различны

8.8. Оператор приведения

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

 Целое число x = 123
Строка s = (Строка) x   (1)  
1 Целое число не может быть присвоено String , поэтому оно создаст ClassCastException во время выполнения

Это можно исправить, используя вместо этого приведение :

 Целое число x = 123
Строка s = x as Строка   (1)  
1 Целое число не может быть присвоено строке , но использование в качестве принудит к строке

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

 класс Идентифицируемый {
    Имя строки
}
класс пользователя {
    Длинный идентификатор
    Имя строки
    def asType (Цель класса) {   (1) 
        если (цель == Идентифицируемый) {
            вернуть новый идентифицируемый (имя: имя)
        }
        выбросить новое исключение ClassCastException («Пользователь не может быть принужден к $ target»)
    }
}
def u = новый пользователь (имя: «Ксавье»)   (2) 
def p = u как идентифицируемый   (3) 
утверждать p instanceof Идентифицируемый   (4) 
assert !(p instanceof User)   (5)  
1 класс User определяет пользовательское правило преобразования из User в Идентифицируемый
2 мы создаем экземпляр пользователя
3 мы принуждаем экземпляр пользователя к идентифицируемому
4 цель является экземпляром Идентифицируемый
5 цель не является экземпляром Пользователь Больше

8.

9. Алмазный оператор

Алмазный оператор ( <> ) является синтаксическим сахарным оператором, добавленным для поддержки совместимости с оператором то же имя в Java 7. Оно используется для указания того, что универсальные типы должны выводиться из объявления:

 List strings = new LinkedList<>() 

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

8.10. Оператор вызова

Оператор вызова () используется для неявного вызова метода с именем call . Для любого объекта, который определяет метод вызова , вы можете опустить часть .call и вместо этого использовать оператор вызова:

 class MyCallable {
    внутренний вызов (int x) {   (1) 
        2*х
    }
}

def mc = новый MyCallable()
утверждать mc. call(2) == 4   (2) 
утверждать mc(2) == 4   (3)  
1 MyCallable определяет метод с именем call . Обратите внимание, что нет необходимости реализовывать java.util.concurrent.Callable
2 мы можем вызвать метод, используя классический синтаксис вызова метода
3 или мы можем опустить .позвоните спасибо оператору звонка

Трюк XOR

Существует множество популярных вопросов на собеседовании, на которые можно ответить одним из двух способов: Либо используя общие структуры данных и алгоритмы разумным образом, либо используя некоторые свойства XOR, казалось бы, трудным для понимания способом.

Хотя кажется неразумным ожидать решения XOR в интервью, довольно интересно выяснить, как они работают. Как оказалось, все они основаны на одном и том же фундаментальном трюке, который мы воспользуемся восходящим подходом в этом посте. После этого мы рассмотрим кучу приложений из этот трюк XOR ™, например, решение этого популярного вопроса интервью:

Вам дан массив из n — 1 целых чисел в диапазоне от 1 до n. Все числа появляются ровно один раз, кроме одного числа, которое отсутствует. Найдите это недостающее число.

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

Исключающее ИЛИ

XOR — логический оператор, работающий с битами. Обозначим его через 9у 0 0 0 0 1 1 1 0 1 1 1 0

Интуитивно это означает, что если мы применяем XOR к одним и тем же аргументам, они нейтрализуют друг друга. 9 — побитовый оператор, он будет работать независимо от того, какие значения a , b и c . Эта идея действительно лежит в основе того, как XOR можно использовать, казалось бы, волшебным образом во многих ситуациях.

Приложение 1: Замена на месте

Прежде чем мы решим задачу поиска пропущенного числа, давайте начнем с этой более простой задачи:

Поменять местами два значения x и y, т. е. без использования каких-либо вспомогательных переменных.

9y просто y (инструкция 3).

Приложение 2: поиск недостающего номера

Давайте, наконец, решим задачу, поставленную в начале этого поста:

Вам дан массив A из n — 1 целых чисел в диапазоне от 1 до n. Все числа появляются ровно один раз, кроме одного числа, которое отсутствует. Найдите это недостающее число.

Конечно, есть много простых способов решить эту проблему, но мы решили сделать это с помощью XOR. 9А [п — 2]

Это даст нам последовательность операторов XOR, где элементы выглядят следующим образом:

  • Все значения в данном списке теперь появляются дважды:
    • один раз из всех значений от 1 до n
    • один раз, потому что они были в исходном списке
  • Отсутствующее значение появляется ровно один раз:
    • один раз из всех значений от 1 до n

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

Просто взглянув на код, этот алгоритм кажется трудным для понимания. Однако, зная, как работает трюк XOR, он становится довольно тривиальным. Я думаю, это также показывает, почему неразумно ожидать такого решения на собеседовании: оно требует знания очень специфического трюка, но не слишком большого алгоритмического мышления.

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

Обобщение этого за пределами целых чисел

Пока мы работали с целыми числами от 1 до n, это не требуется. На самом деле предыдущий алгоритм работает в любой ситуации, когда есть (1) некоторый набор потенциальных элементов и (2) набор реально появляющихся элементов. Наборы могут отличаться только одним отсутствующим элементом. Это хорошо сработало для целых чисел, потому что набор потенциальных элементов просто соответствует элементам от 1 до n.

Можно представить приложения, в которых элементы не являются целыми числами от 1 до n:

  • Набор потенциальных элементов состоит из объектов Person , и мы должны найти Person , отсутствующих в списке значений
  • .
  • Набор потенциальных элементов — это все узлы в графе, и мы ищем недостающий узел
  • Набор потенциальных элементов в общем случае представляет собой целые числа (не обязательно от 1 до n), и мы хотим найти недостающее целое число
Арифметические операторы вместо XOR

Если алгоритм все еще кажется немного волшебным (надеюсь, это не так), полезно подумать о том, как можно добиться того же результата, используя арифметические операторы. Это на самом деле довольно просто:

 по определению find_missing(A, n):
  результат = 0
  # Складываем все значения от 1 до n
  для значения в диапазоне (1, n + 1):
    результат += значение
  # Вычесть все значения в заданном массиве
  для значения в А:
    результат -= значение
  вернуть результат
 

Мы складываем все возможные целые числа, а затем вычитаем те, которые появляются на самом деле. Решение не такое красивое, потому что нужно обрабатывать переполнение и потому что оно требует, чтобы тип элементов поддерживал + , - с определенными свойствами. Однако у него та же логика, когда элементы компенсируют друг друга, потому что они появляются определенное количество раз (один раз положительный, один раз отрицательный).

Приложение 3: поиск повторяющегося номера

Вот где это интересно: мы можем применить то же самое решение к аналогичному вопросу интервью:

Вам дан массив A из n + 1 целых чисел в диапазоне от 1 до n. Все числа появляются ровно один раз, за ​​исключением одного числа, которое дублируется . Найдите этот повторяющийся номер.

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

  • Повторяющееся значение появляется три раза:
    • один раз из всех значений от 1 до n
    • дважды, потому что он дублировался в исходном списке
  • Все остальные значения в данном списке появляются дважды:
    • один раз из всех значений от 1 до n
    • один раз, потому что они были уникальными в исходном списке

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

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

Приложение 4: поиск двух отсутствующих/повторяющихся номеров

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

.

Вам дан массив A из n — 2 целых чисел в диапазоне от 1 до n. Все числа появляются ровно один раз, за ​​исключением двух чисел , которые отсутствуют. Найдите эти два недостающих числа.

Как и прежде, проблема полностью эквивалентна при поиске двух повторяющихся номеров вместо двух отсутствующих номеров .

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

9v , т.е. первая позиция i , где u и v должны отличаться. Затем мы разбиваем на , а также числа от 1 до n в соответствии с этим битом. В итоге имеем два раздела, каждый из которых содержит два набора:

  1. Перегородка 0
    1. Набор всех значений от 1 до n, где i -й бит равен 0
    2. Набор всех значений из A, где i -й бит равен 0
  2. Перегородка 1
    1. Набор всех значений от 1 до n, где i -й бит равен 1
    2. Набор всех значений из A, где i -й бит равен 1

Поскольку u и v различаются позициями i , мы знаем, что они должны быть в разных разделах.

Уменьшение проблемы

Далее мы можем использовать другое понимание, описанное ранее:

Пока мы работали с целыми числами от 1 до n, это не требуется. На самом деле предыдущий алгоритм работает в любой ситуации, когда есть (1) некоторый набор потенциальных элементов и (2) набор реально появляющихся элементов. Наборы могут отличаться только одним отсутствующим (или дублирующимся) элементом.

Эти два набора точно соответствуют наборам, имеющимся в каждом разделе. Таким образом, мы можем найти u , применив эту идею к одному из разделов и найдя недостающий элемент, а затем найти v , применив его к другому разделу.

На самом деле это довольно хороший способ решения: мы эффективно сводим эту новую проблему к более общей версии проблемы, которую мы решили ранее.

Достижение предела

Можно попытаться пойти дальше и попытаться решить проблему для более чем двух пропущенных значений. Я не слишком много думал об этом, но я думаю, что именно здесь мы перестанем добиваться успеха с XOR. Если пропущено (или дублировано) более двух элементов, то анализ отдельных битов невозможен, поскольку возможны несколько комбинаций для обоих 9 элементов. 0016 0 и 1 в качестве результатов.

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

Последние мысли

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

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


Спасибо Eugen за обсуждения, которые привели к этому сообщению. Было весело вместе разбираться, как все это работает.

Обработка битов в Java — операции побитового сдвига и битового сдвига

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

Побитовые операторы

Вы, несомненно, знакомы с арифметическими операторами, такими как + — * / или %. Вы также наверняка знаете такие логические операторы, как & или |. Оказывается, есть еще один, немного менее известный набор операторов, которые манипулируют числами на уровне битов. Внутри каждое число хранится в двоичном формате — то есть 0 и 1.

Эти операторы могут выполняться над целочисленными типами и их вариантами, то есть

  • байт (8 бит)
  • короткий (16 бит)
  • целое число (32 бита)
  • длинный (64 бит)
  • и даже символ (16 бит)

Унарный оператор побитового дополнения [~]

Это причудливое название в основном означает битовое отрицание. Он берет каждый бит числа и переворачивает его значение. То есть — 0 становится 1 и наоборот. Унарный означает, что ему нужен только один операнд. Оператор – это ~, и он ставится перед числом: 9.0005

 ~someVariable 

или

Например, давайте использовать ~42:

  1. Двоичное представление числа 42 равно 101010.
  2. Поскольку 42 — это целое число, оно представляется как 32-битное значение, то есть 32 единицы или нули.
  3. Таким образом, все позиции слева от 101010 на самом деле заполнены нулями до 32 бит.
  4. То есть 00000000 00000000 00000000 00101010
  5. Перевернутое значение числа, указанного выше, тогда будет 11111111 11111111 11111111 11010101

Побитовое И [&]

В отличие от оператора побитового дополнения, другим побитовым операторам требуется два операнда.

A & B означает, что все биты обоих чисел сравниваются один за другим, и результирующее число вычисляется на основе значений битов из чисел A и B. Побитовое И похоже на логическое И в том смысле, что оно приводит к 1 только тогда, когда два сравниваемых бита равны 1. В противном случае это дает 0.

Например: 1010 и 1100 дадут 1000, поскольку первый бит слева является единственным, где оба операнда содержат 1. 9Б 1 0 0 1 1 0 1 0 1 1 1 1 1 1 0 0 0 0 0 0

Операторы битового сдвига

Сдвиг влево со знаком [

<<]

Сдвиг влево со знаком принимает два операнда. Он берет битовую комбинацию первого операнда и сдвигает ее влево на количество разрядов, заданное вторым операндом. Например 5 << 3: Что происходит в этом случае - каждый бит в двоичном представлении целого числа 5 сдвигается на 3 позиции влево. Все места слева заполнены нулями. То есть: 9 н .

Есть несколько дополнительных интересных аспектов:

  • Несмотря на то, что вы можете использовать сдвиг byte, short или char, они преобразуются в 32-битное целое перед сдвигом
  • Операторы битового сдвига никогда не выдают исключение
  • Правый операнд (количество позиций для сдвига) уменьшается по модулю 32. То есть 5 <<35 эквивалентно 5 << 3.

Отрицательные целые числа в Java

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

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

Java использует другой подход, который называется дополнением до двух . Отрицательные числа представляются путем инвертирования (переворачивания) всех битов с последующим добавлением 1. Тем не менее, если крайний левый бит равен 0, число положительное. В противном случае оно отрицательное. 9 n  -1 в случае нечетных чисел.

Сдвиг вправо без знака [>>>]

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

Составные операторы присваивания

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

 х = х + 1; 

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

 x += 1; 

Возможно, вы знакомы с составными операторами присваивания для арифметических операций, таких как += , -= или *= . Но в дополнение к этому Java также предлагает варианты побитовых операторов:

95
Оператор Пример Эквивалентно
&= х &= 5 х = х и 5
<<= х <<= 5 х = х << 5
>>= х >>= 5 х = х >> 5
>>>= х >>>= 5 х = х >>> 5

Обратите внимание, что для унарного оператора побитового дополнения [~] не существует составного оператора присваивания.

Заключение

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

Выражения

Выражения выполняют работу программы Java. Среди прочего, выражения используются для вычисления и присвоения значений переменным и помогают контролировать поток выполнения программы. Задача выражения двояко: выполнить вычисление, указанное элементами выражение и вернуть некоторое значение.
Определение: Выражение представляет собой ряд переменных, операторы и вызовы методов (построенные в соответствии с синтаксисом язык), который возвращает одно значение.

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

количество++;
 
из программы подсчета символов является выражением. Этот конкретный выражение оценивается как значение count перед происходит операция.

Тип данных значения, возвращаемого выражением, зависит от элементы, используемые в выражении. Выражение count++ возвращает целое число, потому что ++ возвращает значение того же тип данных в качестве операнда, а count является целым числом. Другой выражения возвращают логические значения, строки и т. д.

Помимо выражения count++ , подсчет символов программа содержит несколько других выражений, в том числе:

Система.in.read() != -1
 
Это выражение интересно тем, что на самом деле состоит из двух выражения. Первое выражение представляет собой вызов метода:
Система. in.read()
 
Выражение вызова метода оценивается как возвращаемое значение метода; таким образом, тип данных выражения вызова метода совпадает с типом данных тип возвращаемого значения этого метода. System.in.read() метод объявлен возвращающим целое число, поэтому выражение System.in.read() возвращает целое число.

Второе выражение, содержащееся в операторе System.in.read() != -1 является использование оператора != . Напомним, что != сравнивает два своих операнда на неравенство. В рассматриваемом заявлении операнды System.in.read() и -1 . System.in.read() является допустимым операндом для != , потому что System.in.read() — это выражение, результатом которого является целое число. Итак, System.in.read() != -1 сравнивает два целых числа, значение возвращается System.in.read() и -1 . Значение возвращается != либо true или ложь в зависимости от результат сравнения.

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

Возьмем, к примеру, это составное выражение:

х * у * г
 
В этом конкретном примере порядок, в котором вычисляется выражение неважно, потому что результаты умножения не зависят от порядка — результат всегда один и тот же, независимо от того, в каком порядке вы применяете умножения. Однако это верно не для всех выражений. Например, это выражение дает разные результаты в зависимости от того, выполняете ли вы сложение или сначала операция деления:
х + у / 100
 
Вы можете указать компилятору Java явно, как вы хотите, чтобы выражение вычислялось со сбалансированными круглыми скобками ( и ) . Например, чтобы сделать предыдущий оператор недвусмысленным, вы можете написать (х + у)/ 100 .

Если вы явно не укажете компилятору порядок, в котором вы хотите выполнять операции быть выполненным, он решает на основе приоритета , назначенного операторы и другие элементы, используемые в выражении. Операторы с более высокий приоритет оценивается первым. Например, оператор деления имеет более высокий приоритет, чем оператор сложения, поэтому в составном выражение, показанное ранее, x + y / 100 компилятор оценит г/100 первый. Таким образом

х + у / 100
 
эквивалентно
х + (у / 100)
 
Чтобы ваш код было легче читать и поддерживать, вы должны быть явными и укажите в скобках, какие операторы должны оцениваться в первую очередь.

На следующей диаграмме показан приоритет, присвоенный операторам Java. Операторы в этой таблице перечислены в порядке приоритета: чем выше в таблице появляется оператор, тем выше его приоритет. = &= |= <<= >>= >>>=


Поменять местами две переменные, используя XOR – BetterExplained

Большинство людей поменяли бы местами две переменные x и y, используя временную переменную, например:

 tmp = x
х = у
у = tmp
 

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

 x = x xor y
у = х или у
х = х или у
 

Не верите? Попробуйте — запишите любое начальное значение для x и y:

Это почти похоже на волшебство — одно и то же утверждение повторяется 3 раза и 9 раз.1059 вуаля — значения волшебным образом меняются местами? Давайте посмотрим поближе.

Как это работает

Чтобы понять этот трюк, разбейте операторы на уникальные значения:

 x1 = x xor y
у1 = х1 хили у
х2 = х1 или у1
 

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

 x2 = x1 xor y1
x2 = x1 xor (x1 xor y) // заменить y1
x2 = (x1 xor x1) xor y // перегруппировать скобки - порядок не имеет значения для XOR
x2 = 0 xor y // a xor a => 0
x2 = y // 0 xor a => a; x2 теперь имеет исходное значение y
 

Вау, x2 действительно равно y! Обмен произошел. Теперь попробуем для y1:

 y1 = x1 xor y
y1 = (x xor y) xor y
y1 = x xor (y xor y)
у1 = х или 0
y1 = x // y1 == исходное значение x
 

И, тада, трюк снова сработал. x2 и y1 имеют поменявшиеся местами ответы.

Интуитивное понимание

Хорошо, конечно, булева алгебра работает отлично, но это не удовлетворяет. Я хочу, чтобы понимал глубоко внутри и имел смысл, а не был каким-то артефактом свойств XOR. Посмотрим еще раз:

 1: х = х или у
2: у = х или у
3: х = х или у
 

В строке 1 мы объединяем x и y (используя XOR), чтобы получить этот «гибрид», и сохраняем его обратно в x. XOR — отличный способ сохранить информацию, потому что вы можете удалить ее, снова выполнив XOR.

Именно это мы и делаем в строке 2. Мы выполняем XOR над гибридом с y, что отменяет всю информацию y, оставляя нам только x. Мы сохраняем этот результат обратно в y, так что теперь они поменялись местами.

В последней строке x по-прежнему имеет гибридное значение. Мы снова выполняем XOR с y (теперь с исходным значением x), чтобы удалить все следы x из гибрида. Это оставляет нас с y, и обмен завершен!

Вы бы действительно использовали это?

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

Предположим, что x и y являются указателями или ссылками на объекты, и оба указывают на одно и то же место. Мы ожидали, что наша функция подкачки просто поменяет значения без каких-либо изменений, верно?

Посмотрите, что произойдет, если мы расширим строку 1:

 x = x xor y
x = x xor x // x и y равны
х = 0
 

Вау! Таким образом, x сразу же становится равным 0. Это само по себе нормально, но поскольку x и y находятся в одном месте, мы просто сделали y равным нулю! Мы потеряли исходные значения — проблема, известная как алиасинг: изменение одной переменной косвенно влияет на другую.

Итак, вы поймали бы эту ошибку? Я бы этого не сделал, и было бы кошмаром выяснить, почему безобидная функция подкачки вызывает потерю данных. Подобные милые трюки могут быть довольно опасными. Как сказал Брайан Керниган:

Отладка в два раза сложнее, чем написание кода. Следовательно, если вы пишете код максимально умно, вы по определению недостаточно умны, чтобы его отлаживать.

Это очень хорошо здесь применимо — мы написали код настолько умно, насколько могли :). Итак, относитесь к этому как к интеллектуальному упражнению, которое поднимает несколько вопросов:

  • Исключающее ИЛИ — отличный способ объединить информацию, а затем извлечь ее. Шифрование на основе XOR использует этот метод. Кроме того, XOR может объединять N элементов вместе, а не только 2.
  • Появились новые способы выполнения даже самых простых операций.

Еще больше подробностей

Теперь, как это работает на уровне процессора?

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

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

Ваш адрес email не будет опубликован.