Давай поговорим об операциях в Java: числовых, логических, побитовых. Это теоретический базис, который однозначно нужен, чтобы научиться программировать.
Таблица 1. Бинарные арифметические операторы
Первые четыре оператора не должны вызывать вопросов: все так же, как в математике. Последний оператор, остаток от деления, также не делает ничего сверхсложного. К примеру, если разделить 24 на 7, мы получим 3 целых и 3 в остатке. Именно остаток и вернет данный оператор:
Данная программа выведет следующее:
1 + 2 = 3
3 - 1 = 2
2 * 2 = 4
4 / 2 = 2
2 + 8 = 10
10 % 7 = 3
Java позволяет комбинировать: например, операторы присваивания и арифметические операторы.
Рассмотрим пример:
![Знакомство с операторами Java: логические, арифметические, побитовые - 4]()
Помимо бинарных, в Java есть унарные арифметические операторы.
Таблица 2. Унарные арифметические операторы:
Пример унарных плюса и минуса:
![Знакомство с операторами Java: логические, арифметические, побитовые - 6]()
Операции инкремента и декремента по сути просты. В первом случае происходит увеличение переменной на 1, во втором — уменьшение переменной на 1. Пример ниже:
Таблица 3. Операторы инкремента-декремента:
Демонстрация:
![Знакомство с операторами Java: логические, арифметические, побитовые - 8]()
Помимо арифметических, существуют операции сравнения (двух чисел). Результатом всегда будет истина либо ложь (true / false).
Таблица 4. Операторы сравнения
Примеры:
![Знакомство с операторами Java: логические, арифметические, побитовые - 10]()
Таблица 5. Таблица истинности оператора отрицания (NOT) ![Знакомство с операторами Java: логические, арифметические, побитовые - 7]()
Таблица 6. Таблица истинности оператора конъюнкции (AND) ![Знакомство с операторами Java: логические, арифметические, побитовые - 8]()
Таблица 7. Таблица истинности оператора дизъюнкции (OR) ![Знакомство с операторами Java: логические, арифметические, побитовые - 9]()
Таблица 8. Таблица истинности оператора сложения по модулю (XOR)
В Java есть те же логические операции:
![Знакомство с операторами Java: логические, арифметические, побитовые - 15]()
И к ![Знакомство с операторами Java: логические, арифметические, побитовые - 16]()
Теперь, у нас есть сокращенные операторы (![Знакомство с операторами Java: логические, арифметические, побитовые - 17]()
Иногда результат выражения можно вычислить уже по первому операнду. Этим и отличаются сокращенные операторы ![Знакомство с операторами Java: логические, арифметические, побитовые - 18]()
В случае с сокращенными операторами не вычисляется вторая часть выражения. Но происходит это только тогда, когда результат выражения очевиден уже по первому операнду.
Продемонстрируем счет от 0 до 15 в десятичной системе и в двоичной:
Как видим, все не так уж и сложно.
Помимо битов, есть другие знакомые единицы измерения информации — байты, килобайты, мегабайты, гигабайты и тд.
Ты, наверно, знаешь, что в 1 байте — 8 бит. Что это значит? Это значит, что 8 битов подряд занимают 1 байт. Вот примеры, какими могут быть байты:
Рассмотрим тип ![Знакомство с операторами Java: логические, арифметические, побитовые - 21]()
Вуаля — все не так уж и сложно. Но все-таки кое-что следует уточнить. Рассмотрим это на примере 8-ми битного числа:
Подход несложный и в принципе понятный. Однако у него есть недостатки: возникают трудности с выполнением математических операций. К примеру со сложением отрицательных и положительных чисел. Их нельзя складывать, если не провести дополнительные манипуляции.
Как мы уже выяснили числа можно представить в виде набора битов. Побитовые операции осуществляют операции как раз над каждым битом такого представления.
Возьмем
Давай взглянем как это выглядит в Java коде:
![Знакомство с операторами Java: логические, арифметические, побитовые - 25]()
В первой строке мы получили значение в двоичной системе счисления без ведущих нулей. Хоть мы их не видим, они есть. Об этом говорит вторая строка, в которой все биты трансформировались в обратные. Именно поэтому мы видим так много ведущих единиц. Это бывшие ведущие нули, которые игнорировались компилятором при выводе в первой строки.
Вот небольшая программа, которая выводит для наглядности еще и ведущие нули.
![Знакомство с операторами Java: логические, арифметические, побитовые - 26]()
Данная операция осуществляется над двумя числами. Пример в Java коде:
![Знакомство с операторами Java: логические, арифметические, побитовые - 28]()
Теперь взглянем на то, как бы это выглядело в IDEA:
![Знакомство с операторами Java: логические, арифметические, побитовые - 30]()
Пример кода:
![Знакомство с операторами Java: логические, арифметические, побитовые - 32]()
Результатом операции будет число 20 в десятичной системе.
Как видно из схемы выше, все биты сдвигаются влево на 1. При этой операции значение старшего бита (крайнего левого) теряется. А самый младший бит (крайний правый) заполняется нулем.
Что можно сказать об этой операции?
При операции сдвига мы теряем правые биты. Они попросту исчезают.
Крайний левый бит — показатель знака числа (0 — число положительное, 1 — отрицательное). Поэтому в итоговом значении он ставится таким же, как и в исходном числе. Пример с отрицательным числом:
Крайний правый бит потерялся, а крайний левый бит скопирован из исходного числа, как почетный показатель знака числа.
Как это все осуществить в IDEA? В принципе, ничего сложного, просто берем и сдвигаем:
![Знакомство с операторами Java: логические, арифметические, побитовые - 38]()
Теперь. Что можно сказать о числах, над которыми осуществляется сдвиг вправо? Они делятся на 2. Каждый раз, осуществляя сдвиг на один бит вправо мы делим исходное число на 2. Если число нацело на 2 не делится, результат будет округлен в сторону минус бесконечности (в меньшую сторону).
Но это работает, только если мы сдвигаем биты ровно на 1.
А если на 2 бита, делим на 4.
На 3 бита — делим на 8.
На 4 бита — на 16.
Видишь? Степени двойки…
При сдвиге числа ![Знакомство с операторами Java: логические, арифметические, побитовые - 22]()
![Знакомство с операторами Java: логические, арифметические, побитовые - 23]()
![Знакомство с операторами Java: логические, арифметические, побитовые - 24]()
Для поиска минимального элемента просто меняем знак сравнения в нужном месте.

- Какие бывают операторы в Java
- Операторы Java в курсе JavaRush
- Операции над числами в Java
- Логические операции в Java
- Побитовые операции в Java
- Приоритет операций в Java
- Полезные примеры использования
Какие бывают операторы в Java
Для любой операции нам нужно как минимум две вещи:- оператор;
- операнд.
Операторы Java в курсе JavaRush
Несколько лекций посвящено операторам Java на четвертом уровне первого квеста — Java Syntax. В частности, условным операторам, типу boolean. В курсе есть 22 задачи, которые помогут разобраться с работой операторов сравнения, условных, логических операторов.Операции над числами в Java
Самая частая операция, которую программисты производят над числами — присвоение числового значения какой либо переменной. Она, как и оператор=
тебе знакомы:
int a = 1;
int b = 2;
int c = 3;
Есть также арифметические операции. Они осуществляются с помощью бинарных арифметических операторов:

System.out.println(24 % 7); // выведет 3
Вот примеры с сайта официальной документации Oracle:

int x = 0;
x = x + 1; // x = 0 + 1 => x = 1
x = x + 1; // x = 1 + 1 => x = 2
x = x + 1; // x = 2 + 1 => x = 3
Здесь мы задали переменную x
и присвоили ей нулевое значение. Далее в каждой строке мы присваиваем значению x
сумму текущего значения переменной x
и единицы. В комментариях к каждой строке есть пояснения. Эту процедуру называют наращиванием или инкрементированием переменной.
Операцию инкрементирования из примера выше можно заменить на аналогичную с использованием комбинации операторов:
int x = 0;
x += 1; // x = 0 + 1 => x = 1
x += 1; // x = 1 + 1 => x = 2
x += 1; // x = 2 + 1 => x = 3
Комбинировать оператор присваивания можно с любым арифметическим оператором:
int x = 0;
x += 10; // x = 0 + 10 => x = 10
x -= 5; // x = 10 - 5 => x = 5
x *= 5; // x = 5 * 5 => x = 25
x /= 5; // x = 25 / 5 => x = 5
x %= 3; // x = 5 % 3 => x = 2;
Продемонстрируем работу последнего примера:


int x = 0;
x = (+5) + (+15); //Скобки для наглядности, можно и без них
System.out.println("x = " + x);
int y = -x;
System.out.println("y = " + y);

int x = 9;
x++;
System.out.println(x); // 10
int y = 21;
y--;
System.out.println(y); // 20
Есть два типа данных операций — постфиксная и префиксная. В первом случае оператор пишется после переменной, во втором случае — перед переменной. Разница лишь в том, когда выполнится операция инкрементирования или декрементирования. Пример и описание в таблице ниже.
Предположим, у нас есть переменная:
int a = 2;
Тогда:



int a = 1;
int b = 2;
boolean comparisonResult = a == b;
System.out.println("a == b :" + comparisonResult);
comparisonResult = a != b;
System.out.println("a != b :" + comparisonResult);
comparisonResult = a > b;
System.out.println("a > b :" + comparisonResult);
comparisonResult = a >= b;
System.out.println("a >= b :" + comparisonResult);
comparisonResult = a < b;
System.out.println("a < b :" + comparisonResult);
comparisonResult = a <= b;
System.out.println("a <= b :" + comparisonResult);
Демонстрация:

Логические операции в Java
Рассмотрим логические операции и таблицы истинности каждой из них:- операция отрицания (
NOT
); - операция конъюнкции, логическое И (
AND
); - операция дизъюнкции, логическое ИЛИ (
OR
); - операция сложения по модулю, исключающее ИЛИ (
XOR
).




!
— оператор отрицания;&&
— оператор логическое И (сокращенный);||
— оператор логическое ИЛИ (сокращенный);&
— оператор побитовое И;|
— оператор побитовое ИЛИ;^
— оператор побитовое исключающее ИЛИ.
public class LogicDemo {
public static void main(String[] args) {
notExample();
andExample();
orExample();
xorExample();
}
public static void notExample() {
System.out.println("NOT EXAMPLE:");
System.out.println("NOT false = " + !false);
System.out.println("NOT true = " + !true);
System.out.println();
}
public static void andExample() {
System.out.println("AND EXAMPLE:");
System.out.println("false AND false = " + (false & false));
System.out.println("false AND true = " + (false & true));
System.out.println("true AND false = " + (true & false));
System.out.println("true AND true = " + (true & true));
System.out.println();
}
public static void orExample() {
System.out.println("OR EXAMPLE:");
System.out.println("false OR false = " + (false | false));
System.out.println("false OR true = " + (false | true));
System.out.println("true OR false = " + (true | false));
System.out.println("true OR true = " + (true | true));
System.out.println();
}
public static void xorExample() {
System.out.println("XOR EXAMPLE:");
System.out.println("false XOR false = " + (false ^ false));
System.out.println("false XOR true = " + (false ^ true));
System.out.println("true XOR false = " + (true ^ false));
System.out.println("true XOR true = " + (true ^ true));
System.out.println();
}
}
Данная программа выведет на экран:
NOT EXAMPLE:
NOT false = true
NOT true = false
AND EXAMPLE:
false AND false = false
false AND true = false
true AND false = false
true AND true = true
OR EXAMPLE:
false OR false = false
false OR true = true
true OR false = true
true OR true = true
XOR EXAMPLE:
false XOR false = false
false XOR true = true
true XOR false = true
true XOR true = false
Логические операторы применимы только к boolean
переменным. В нашем случае мы применяли их сразу к значениям, но можно их использовать и с boolean
переменными:

boolean
выражениям:

&&
, ||
) и аналогичные побитовые операторы (&
, |
). В чем между ними разница?
Во-первых, побитовые можно применять к целым числам. Об этом мы поговорим чуть позже.
А во-вторых, одни сокращенные, а другие — нет. Чтобы понять, как выглядит сокращенность, посмотрим на выражение:
false AND x = ?
true OR x = ?
Здесь x
может принимать любое булево значение. И в целом, согласно законам логики и таблицам истинности, независимо от того, будет x
true или false, результатом первого выражения будет false, а результатом второго будет true. Смотри.

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

Побитовые операции в Java
Ну вот мы и подобрались к самому интересному: побитовым операциям. Как можно понять из названия, это операции, которые производятся над битами. Но прежде чем мы погрузимся в эту тему, стоит поговорить о смежных областях.Представление чисел в двоичной системе счисления
Числа, как и любая другая информация в программе, хранятся в памяти компьютера в двоичном коде. Двоичный код — набор нулей и единиц. Каждый ноль или единица представляют собой единицу измерения информации, которая называется бит.Согласно Википедии:
Бит (от англ. binary digit — двоичное число; также игра слов: англ. bit — кусочек, частица) — единица измерения количества информации. 1 бит информации — это символ или сигнал, который может принимать два значения: включено или выключено, да или нет, высокий или низкий, заряженный или незаряженный; в двоичной системе исчисления это 1 (единица) или 0 (ноль).С какими данными работают побитовые операторы?
Побитовые операции в Java осуществляются только над целыми числами. А целые числа хранятся в памяти компьютера в виде набора битов. Можно сказать, что компьютер переводит любую информацию в двоичную систему счисления (в набор битов) и только потом взаимодействует с ней. Но как устроена двоичная система счисления? В десятичной системе счисления у нас есть всего 10 символов: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. С помощью этих символов мы ведем счет. После 9 идет 10, после 19 — 20, после 99 — 100, после 749 — 750. То есть мы используем комбинацию имеющихся 10 символов и можем с их помощью считать «от нуля и до обеда». В двоичной системе счисления вместо десяти символов есть всего два — 0, 1. Но комбинируя эти символы по тому же принципу, что и в десятичной системе, можем считать бесконечно долго.
00000000 - 1 байт
10110010 - 1 байт
01011011 - 1 байт
Количество возможных неповторяющихся комбинаций битов в одном байте — 256 (28 = 256).
Но вернемся ближе к Java. Есть такой целочисленный тип данных — byte
. Данный тип может принимать значения от -128 до 127 и одно число в памяти компьютера занимает ровно 8 бит, или 1 байт. Одно число этого типа занимает ровно 1 byte
памяти компьютера. И здесь названия совпадают не случайно.
Как мы помним, 1 байт может хранить 256 различных значений. И одно число типа byte
может принимать 256 различных значений (128 отрицательных, 127 положительных и 1 ноль).
Каждому значению числа byte
соответствует уникальный набор из восьми битов. Так обстоят дела не только с типом byte
, но и со всеми целочисленными типами. Тип byte
приведен в пример как самый маленький. Ниже в таблице представлены все целочисленные типы Java и занимаемое ими место в памяти:

int
. Он может хранить 2147483648 отрицательных, 2147483647 положительных значений и один ноль. Итого:
2147483648 + 2147483647 + 1 = 4294967296.
Данный тип занимает в памяти компьютера 32 бита. Количество возможных комбинаций из набора 32-ух нулей и единиц равно:
232 = 4294967296.
То же число, что и у количества значений, вмещаемых в тип int
.
Это всего лишь демонстрация взаимосвязи между диапазоном значений типа данных и его размером (количество бит в памяти).
Любое число любого типа в Java можно перевести в двоичную систему счисления. Давай посмотрим, как легко это можно сделать это с помощью Java языка.
Будем учиться на примере типа int
. У данного типа есть свой класс-обертка — Integer
. А у него — toBinaryString
, который и сделает за нас всю работу:

int
число занимает 32 бита. Но когда мы выводим число 10 в примере выше, мы видим в консоли 1010. Это потому, что ведущие нули не выводятся на печать. Если бы они выводились, вместо 1010 мы бы видели в консоли 00000000000000000000000000001010. Но для удобства восприятия все ведущие нули опускаются.
Не так уж и сложно до тех пор, пока не задашься вопросом: а что с отрицательными числами?
Он воспринимает информацию только в двоичной системе. Получается, что знак минус также необходимо прописывать двоичным кодом. Это можно сделать с помощью прямого или дополнительного кода.
Прямой код
Способ представления чисел в двоичной системе счисления, при котором старший разряд (крайний левый бит) отводится под знак числа. Если число положительное, в крайний левый бит записывается 0, если отрицательное — 1.
Дополнительный код
Используя дополнительный код, можно избежать недостатков прямого кода. Для получения дополнительного кода числа есть несложный алгоритм. Попробуем получить дополнительный код числа -5. Представим это число с помощью дополнительного кода в двоичной системе счисления. Шаг 1. Получаем представление отрицательного числа с помощью прямого кода. Для -5 это будет 10000101. Шаг 2. Инвертируем все разряды, кроме разряда знака. Заменим все нули на единицы, а единицы на нули везде, кроме крайнего левого бита.
10000101 => 11111010
Шаг 3. К полученному значению прибавим единицу:
11111010 + 1 = 11111011
Готово. Мы получили значение числа -5 в двоичной системе счисления с использованием дополнительного кода.
Это важно для понимания дальнейшего материала, так как в Java для хранения отрицательных чисел в битах используется дополнительный код.
Типы побитовых операций
Теперь, когда мы разобрались со всеми вводными, поговорим о побитовых операциях в Java. Побитовая операция осуществляется над целыми числами, и ее результатом будет целое число. В процессе число переводится в двоичную систему, над каждым битом выполняется операция, и результат приводится обратно в десятичную систему. Список операций — в таблице ниже:
NOT
, AND
, OR
, XOR
. Вспомним, что недавно мы рассматривали таблицы истинности, только для логических операндов. В данном случае те же операции применяются к каждому биту целого числа.
Побитовый унарный оператор NOT ~
Данный оператор заменяет все нули на единицы, а единицы — на нули. Предположим, у нас есть число 10 в десятичной системе исчисления. В двоичной системе это число равно 1010. Если применить к данному числу унарный побитовый оператор отрицания, мы получим примерно следующее:
public static void main(String[] args) {
int a = 10;
System.out.println(" a = " + a + "; binary string: " + Integer.toBinaryString(a));
System.out.println("~a = " + ~a + "; binary string: " + Integer.toBinaryString(~a));
}
Теперь посмотрим, что выведется в консоль:


Побитовый оператор AND
Данный оператор применим к двум числам. Он производит операциюAND
между битами каждого числа. Рассмотрим пример:


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

Побитовая операция, исключающее ИЛИ (XOR)
Взглянем на тот же пример, но с новой операцией:

Побитовый сдвиг влево
Данный оператор применим к двум операндам, то есть в операцииx << y
, биты числа x
сдвинутся на y
позиций влево.
Что это значит? Рассмотрим на примере операции 10 << 1

Сдвигая биты числа
X
наN
битов влево мы умножаем числоX
на 2N.Вот пример:
Но! У нас может измениться знак числа, если бит со значением 1 займет крайнее левое положение.
Если осуществлять сдвиг влево бесконечно долго, число просто превратится в 0. Продемонстрируем пункты 2 и 3:
Побитовый сдвиг вправо
Данный оператор применим к двум операндам. Т.е. в операцииx >> y
, биты числа x
сдвинутся на y
позиций вправо.
Рассмотрим другой пример. Схематично разберем операцию 10 >> 1
. Сдвинем все биты числа 10 на одну позицию вправо:



X
на N
битов вправо, мы делим число X
на 2 в степени N
.
Демонстрация:
public class BitOperationsDemo {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
int shiftOperationResult = 2048 >> i;
int devideOperationResult = 2048 / (int) Math.pow(2, i);
System.out.println(shiftOperationResult + " - " + devideOperationResult);
}
}
}
Что тут происходит?
Цикл, в котором переменная i наращивается от 1 до 10.
- Каждую итерацию мы вычисляем 2 значения:
в переменную
shiftOperationResult
записываем результат сдвига числа 2048 на i битов вправо;в переменную
devideOperationResult
записываем результат деления числа 2048 на 2 в степени i.Попарно выводим два полученных значения.
Побитовый сдвиг вправо с заполнением нулями
Если обычный сдвиг битов вправо сохраняет знак числа (старший бит сохраняет свое значение), в случае со сдвигом вправо с заполнением нулями этого не происходит. А происходит заполнение старшего бита нулем. Давай посмотрим, как это выглядит:
Приоритет операций в Java
Как и в математике, в Java есть приоритет операций. В таблице ниже приведен приоритет (от высшего к низшему) рассмотренных нами операций.
Полезные примеры использования
Определение четности числа

Поиск максимального элемента в массиве

ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
битахбайтах используется дополнительный код."