Логическое и побитовое "И"
Очень часто, молодых специалистов легко завести в тупик, спросив чем отличаются два условия:
if (a&&b){} и if (a&b){}. Сегодня я расскажу в чем отличие.
Для начала нам необходимо знать, что:
&& = это логическое "И"
& = это битовое "И"
Давайте посмотрим что нам говорит Wikipedia:
В компьютерных языках используется два основных варианта конъюнкции: логическое "И" и побитовое (поразрядное) "И". Например, в языках C/C++ логическое "И" обозначается символом "&&", а побитовое — символом "&". В терминологии, используемой в C#, операцию "&" принято называть логическим "И", а операцию "&&" - условным "И", поскольку значения операндов являются условиями для продолжения вычисления. В языках Pascal/Delphi оба вида конъюнкции обозначается с использованием ключевого слова "and", а результат действия определяется типом операндов. Если операнды имеют логический тип (например, Boolean) — выполняется логическая операция, если целочисленный (например, Byte) — поразрядная.
Если Вы все поняли, можете дальше не читать. Для тех же, кто в цитате увидел, просто набор букв, я объясню проще:
- При использовании && происходит логическое сравнение, двух результатов,
например: false && true = false - При использовании & происходит побитовое сравнение, двух результатов,
например: 001 & 101 = 001
Это в свою очередь нам дает такой результат:
- При использовании &&, в случае, если результат равен false, дальнейшая проверка не выполняется.
Пример: (false && a() && b()). Методы a() и b() не будут вызваны, т.к. на первом месте стоит false и это означает что все выражение будет false. - При использовании &, в любом случае будут выполнены все проверки, т.к. побитовый сдвиг "надо делать с цифрами", а на этапе выполнения выражения, мы не можем предсказать результат.
Пример: (false & a() & b()) . Методы a() и b() будут вызваны.
Давайте теперь проверим:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class Main { private static int counter=0; public static void main(String[] args) { if (test() && test()); System.out.println("------------"); counter=0; if (test() & test()); } public static boolean test() { counter++; System.out.println("Test run. Iteration: "+counter); return false; } } |
Результат выполнения:
1 2 3 4 5 6 |
Test run. Iteration: 1 ------------ Test run. Iteration: 1 Test run. Iteration: 2 |
Итак, в первом случае я использую логическое "и" (&&) и мы видим что метод test() выполняется только один раз (тот что слева от &&), т.к. он возвращает false, то компилятор оптимизирует вычисления и второй вызов test() не делает.
Во втором случае, мы используем побитовое "и" (&), соответственно для вычисления результата компилятору необходимо знать оба результата, поэтому метод тест вызывается дважды (тот что слева от & и тот что справа).
Вопросы для собеседования:
- Чему будет равно выражение: ( false ) && ( false & true && true & false & false && true )
Ответ: результат будет false, т.к. слева у нас false, и дальше оператор логического "и" (&&), а это значит что выражение во вторых скобках компилятор не будет считать. - Чему будет равно выражение: if ( 1 & 1 && 1 ){}
Ответ: Ничему. Произойдет ошибка компиляции. Тут допущено три ошибки:
а) if должен на вход получать boolean значение, а у нас int;
б) операция && (логическое "и") может быть выполнена только с boolean значениями;
в) операция & (побитовое "и") может быть выполнена только с цифрами.
Author: | Tags: /
| Rating:
2 comments.
Write a comment