Перейти к содержимому

Какие из следующих операторов называются укороченными

  • автор:

Java

&copy 2008 Наталия Македа
Все материалы блога защищены авторским правом. Любая перепечатка или использование материалов этого блога в коммерческих целях возможна лишь с письменного согласия автора. При некоммерческом использовании ссылка на блог обязательна.

среда, 20 августа 2008 г.

2.7 Укороченные (short-circuit) логические операторы (Выпуск 10)

Укороченные (short-circuit) логические операторы && и || предназначаются для логических AND (И) и OR (ИЛИ) операций над выражениями типа boolean . Заметьте, что для XOR (исключающее ИЛИ) операции не существует укороченного логического оператора.

Укороченные логические операторы похожи на операторы & и |, но в отличие от них применяются только к выражениям типа boolean и никогда не применяются к интегральным типам. Тем не менее, && и || обладают замечательным свойством: они укорачивают вычисление выражения, если результат может быть дедуцирован из части выражения (чуть позже я поясню это на примерах). Благодаря этому свойству, операторы && и || широко используются для обработки null-выражений. Они также помогают увеличить эффективность всей программы.

  • выражение с AND оператором ложно ( false ), если значение хотя бы одного из его операндов ложно;
  • выражение с OR оператором истинно ( true ), если значение хотя бы одного из его операндов истинно.
  • false AND X = false
  • true OR X = true

Рассмотрим пример кода, который выводит сообщение String , если строка не нулевая и более 20 символов длиной:

Эта же задача может быть закодиравана по-другому:

1. if (s != null) <
2. if (s.length() > 20) <
3. System.out.println(s);
4. >
5. >

Если бы строка s была null , то при вызове метода s.length() мы бы получили NullPointerException . Ни в одном из двух примеров кода, однако, такая ситауция не возникнет. В частности, во втором примере, s.length() не вызывается при s = null , благодаря использованию укороченного оператора &&. Если бы тест (s!=null) возвращал ложь ( false ), то есть s — несуществующая строка, то и всё выражение гарантированно ложно. Значит, отпадает необхеодимость вычислять значение второго операнда, то есть выражения (s.length()>20) .

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

// первый пример 1. int val = (int)(2 * Math.random()); 2. boolean test = (val == 0) || (++val == 2); 3. System.out.println(“test = “ + test + “\nval = “ + val); // второй пример 1. int val = (int)(2 * Math.random()); 2. boolean test = (val == 0)|(++val == 2); 3. System.out.println(“test = “ + test + “\nval = “ + val);

Первый пример иногда будет выводить на печать вот это:

test = true
val = 0

А иногда вот это:

test = true
val = 2

Второй пример иногда будет выводить на печать вот это:

test = true
val = 1

А иногда вот это:

test = true
val = 2

А дело вот в чём. Если val равно 0, то второй операнд (++val) никогда не будет вычислен, то есть val останется равным нулю. Если же изначально val равен единице, то в результате эта переменная будет инкрементирована и мы увидим val = 2 . Во втором примере, при использовании неукороченных операторов, инкремент выполняется всегда и результат будет всегда или 1 или 2 в зависимости от случайного значения выбранного на первом шаге. В обоих примерах переменная test принимает значение true , потому что либо val = 0 , либо val = 1 и инкрементируется до значения 2.

  • Они применяются к операндам типа boolean ;
  • Они вычисляют значение правого операнда только если результат не может быть вычислен на основании значения левого операнда:
    • false AND X = false
    • true OR X = true

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

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

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

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

    1. Логические операторы OR, AND, XOR, NOT.

    Начнем с операций OR(|), AND(&), XOR(^), NOT(!). Операторы OR, AND, XOR являются бинарными — они требуют два оператора. NOT — это унарный оператор, только один оператор участвует в операции. Результаты выполнения этих логических операций представлены в следующей таблице:

    A B A|B A&B
    A^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

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

    AND (&) — результат будет true , только если и A, и B равны true . Пример: для того чтобы свадьба состоялась, и невеста (A) и жених (B) должны явиться на бракосочетание, иначе оно не состоится.

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

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

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

    public class BooleanLogic1 < public static void main(String[] args) < boolean a = true; boolean b = false; boolean c = a | b; boolean d = a & b; boolean e = a ^ b; boolean f = (!a & b) | (a & !b); boolean g = !a; System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("a | b = " + c); System.out.println("a & b = " + d); System.out.println("a ^ b = " + e); System.out.println("(!a & b) | (a & !b) = " + f); System.out.println("!a header3">2. Укороченные логические операторы (short-circuit). 

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

    || - Укороченный логический оператор ИЛИ
    && - Укороченный логический оператор И

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

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

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

    public class BooleanLogic2 < public static void main(String[] args) < int d = 0; int num = 10; if (d != 0 && num / d >10) < System.out.println("num language-java">public class BooleanLogic3 < public static void main(String[] args) < int a = 1; int b = 2; int x = 3; System.out.print(a < x && x < b); // System.out.print(a < x < b);//Ошибка компиляции >>

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

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

    public class BooleanLogic4 < public static void main(String[] args) < boolean b1 = true; boolean b2 = false; System.out.println(b1 == b2); System.out.println(b1 != b2); >>

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

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

    public class BooleanLogic5 < public static void main(String[] args) < boolean b1 = true; boolean b2 = true; b1 &= b2;//равносильно b1 = b1 & b2; System.out.println(b1); b1 |= b2; //равносильно b1 = b1 | b2; System.out.println(b1); b1 ^= b2; //равносильно b1 = b1 ^ b2; System.out.println(b1); >>

    Презентацию с видео можно скачать на Patreon .

    2. Укороченные логические операторы

    В С# предусмотрены также специальные, укороченные, варианты логических операторов И и ИЛИ, предназначенные для получения более эффективного кода. Поясним это на следующих примерах логических операций. Если первый операнд логической операции И имеет ложное значение false, то её результат будет иметь ложное значение независимо от значения второго операнда. Если же первый операнд логической операции ИЛИ имеет истинное значение true, то её результат будет иметь истинное значение независимо от значения второго операнда. Благодаря тому, что значение второго операнда в этих операциях вычислять не нужно, экономится время и повышается эффективность кода.

    Укороченная логическая операция И выполняется с помощью оператора &&, а укороченная логическая операция ИЛИ — с помощью оператора ||. Этим укороченным логическим операторам соответствуют обычные логические операторы & и |. Единственное отличие укороченного логического оператора от обычного заключается в том, что второй его операнд вычисляется только по мере необходимости.

    Укороченные логические операторы иногда оказываются более эффективными, чем их обычные аналоги. Так зачем же нужны обычные логические операторы И и ИЛИ? Дело в том, что в некоторых случаях требуется вычислять оба операнда логической операции И либо ИЛИ из-за возникающих побочных эффектов. Пример:

    static void Main()

    short d = 12, f = 1, i = 0;

    // В данном случае используется укороченный оператор

    // и операция сравнения выполнится в нормальном потоке

    if (f != 0 && (d % f) == 0)

    Console.WriteLine(" делится нацело на ", d, f);

    // В этом случае так же используется укороченный оператор,

    // но при этом возникнет исключительная ситуация

    // т.к. первый оператор сравнения содержит деление на 0

    if ((d % f) == 0 && f != 0)

    Console.WriteLine(" делится нацело на ", d, f);

    // При использовании целостного оператора в любом

    // случае возникнет исключительная ситуация

    if (f != 0 & (d % f) == 0)

    Console.WriteLine(" делится нацело на ", d, f);

    // Практический пример использования обычных операторов.

    // При использовании обычного оператора, в данной конструкции

    // i будет инкреминироваться

    Console.WriteLine("i равно ", i); // i = 1

    // При использовании укороченного оператора

    // значение i останется прежним

    Console.WriteLine("i равно ", i); // i = 0

    Console.WriteLine("Для продолжение нажмите любую клавишу . . . ");

    * 12 делится нацело на 1

    * 12 делится нацело на 1

    * 12 делится нацело на 1

    * Для продолжение нажмите любую клавишу . . .

    Если в коде примера выше переменной f задать число «0, будет выдано исключение «деления на ноль»: DivideByZeroException.

    Какие из следующих операторов называются укороченными

    -7 это именно 11111111 11111111 11111111 11111001, а 10000000 00000000 00000000 00000111 это уже очень близко к самому отрицательному - минус два ядра чего-то там или 1(31ноль) в двоичном. А так хорошая очень статья, без неё совсем худо было бы. Ну и в целом - получается, если нужен отрицательное двоичное число, его можно "сделать" из положительного: меняем все знаки на противоположные, прибавляем единицу - готово.

    Mick Thomson Уровень 14
    28 марта 2023
    что-то не понял, 10000000 00000000 00000000 00000111 это -2147483641, а не -7
    2 марта 2023

    Почему в примере операции побитового отрицания число -13 записано в дополнительном коде? Операция ~ тоже применяется к дополнительному коду?

    Serge Уровень 26
    19 марта 2022
    про дополнительный код так и не понял
    Сергей Д. Уровень 37
    11 ноября 2021

    Почему 11111111 11111111 11111111 11110011 - это -13? Не я проверил. Написал ~12, да выдало -13. Почему 1100 - это 12 ясно, а вот как 11111111 11111111 11111111 11110011 стало минус 13 - не ясно

    15 ноября 2020
    Отличная статья, рекомендовал бы любому время от времени перечитывать)
    1 июня 2020

    Может кто объяснить, зачем побитовое мне щас? достаточно знать &&, || и все же? да и вообще в будущем все это побитовое лучше же исключить, чтоб код был читаемый без всего этого.

    Серго Уровень 12
    12 января 2020

    может мне кто нибудь обьяснить, как печатать с клавы эти символы ||||||, я уже горю, даже в гугле найти не могу:DDDD А копипастить из лекций надоело

    4 января 2020
    Приятно удивлён, что АЖ на 10 уровне будут темы из уроков информатики, 6 класс
    Миша Небоярски Уровень 16
    12 сентября 2019

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

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

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