Javascript — операторы

Знак плюс

Знак плюс (+) является бинарным оператором, который указывает на операцию сложения, например, 31 + 5 = 36. Также может выступать унарным оператором, который оставляет свой операнд без изменений («+х» означает то же самое, что и «х»). Знак плюса может использоваться, когда необходимо подчеркнуть положительность числа в противоположность отрицательному (+5 против −5).

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

Кроме того, плюс может также означать:

  • исключающее «ИЛИ» (обычно записывается ⊕): 1 + 1 = 0, 1 + 0 = 1
  • логическое сложение (обычно записывается ∨): 1 + 1 = 1, 1 + 0 = 1.

Примеры применения унарной системы

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

  1. Обычный процесс счёта на пальцах.
  2. Подсчитывание числа людей, посетивших какую-то организацию за определённый временной интервал.
  3. Операция подсчёта количества голосов на выборах в какую-либо структуру власти.
  4. Первоклассников обучают процедуре счёта и простым арифметическим действиям как раз с применением унарной системы посредством разноцветных палочек.
  5. В информационных дисциплинах унарная система счисления применяется для разрешения отдельных проблем, к примеру, вычислительной сложности. Чтобы это сделать, необходимо привести числовое значение к унарному виду, поскольку тогда его легко можно представить в виде составляющих элементов, каждый из которых можно обрабатывать параллельными вычислениями на компьютере.

Унарные постфиксные операторы

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

Если внешняя операторная функция унарного оператора будет иметь вид:

CC operator##(AA aa, int)

{

// Тело …

}

то в тексте программы программист может заменить ее явный вызов

operator## (aa, num);

привычным выражением аа##. Здесь num – аргумент, значение которого в функции не используется (фиктивный аргумент).

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

Если операторная функция-член класса для унарного оператора имеет вид:

CC AA::operator##( int )

{

// Тело …

}

то в тексте программы программист может заменить ее явный вызов

aa.operator##(num);

тем же выражением аа##.

Полезно будет отметить, что операторные функции-члены класса всегда должны быть

нестатическими1.

Записи

Мультипликативная запись

Если абстрактную бинарную операцию на M{\displaystyle M} называют умноже́нием, то её результат для элементов x,y∈M{\displaystyle x,\;y\in M} называют их произведе́нием и обозначают x⋅y{\displaystyle x\cdot y} или xy{\displaystyle xy}. В этом случае нейтральный элемент e∈M{\displaystyle e\in M}, то есть элемент удовлетворяющий равенствам

x⋅e=e⋅x=x,∀x∈M,{\displaystyle x\cdot e=e\cdot x=x,\quad \forall x\in M,}

называется едини́чным элеме́нтом относительно выбранной бинарной операции.

Аддитивная запись

Если бинарную операцию называют сложе́нием, то образ пары элементов x,y∈M{\displaystyle x,\;y\in M} называют су́ммой и обозначают x+y{\displaystyle x+y}. Обычно, если бинарную операцию называют сложением, то она предполагается коммутативной. Нейтральный элемент в аддитивной записи обозначают символом 0, называют нулевы́м элеме́нтом и пишут

x+=+x=x,∀x∈M.{\displaystyle x+0=0+x=x,\quad \forall x\in M.}

Унарная операция проекции

Скрыть рекламу в статье

2. Унарная операция проекции

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

Оператор проекции обозначается [S’] или ?<S’>. Здесь S’ – подсхема исходной схемы отношения S, т. е. ее некоторые столбцы. Что это означает? Это означает, что у S’ атрибутов меньше, чем у S, потому что в S’ остались только те из них, для которых выполнилось условие проекции. А в таблице, представляющей отношение r(S’ ), строк столько же, сколько их у таблицы r(S), а столбцов – меньше, так как остались только соответствующие оставшимся атрибутам. Таким образом, оператор проекции ?< S’> применительно к отношению r(S) дает в результате новое отношение с другой схемой отношения r(S’ ), состоящее из проекций t(S) [S’ ] кортежей исходного отношения. Как определяются эти проекции кортежей? Проекция любого кортежа t(S) исходного отношения r(S) на подсхему S’ определяется следующей формулой:

t(S) [S’] = {t(a)|a ? def(t) ? S’}, S‘ ?S.

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

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

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

?<S’>r(S) ? ?<S’>r ? r(S) [S’] ? r [S’ ] = {t(S) [S’] | t ? r };

Рассмотрим пример, иллюстрирующий принцип работы операции выборки.

Пусть дано отношение «Сессия» и схема этого отношения:

S: Сессия (№ зачетной книжки, Фамилия, Предмет, Оценка);

Нас будут интересовать только два атрибута из этой схемы, а именно «№ зачетной книжки» и «Фамилия» студента, поэтому подсхема S’ будет выглядеть следующим образом:

S’ : (№ зачетной книжки, Фамилия).

Нужно исходное отношение r(S) спроецировать на подсхему S’.

Далее, пусть нам дан кортеж t(S) из исходного отношения:

t(S) ? r(S): {(№ зачетной книжки: 100), (Фамилия: ‘Иванов’), (Предмет: ‘Базы данных’), (Оценка: 5)};

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

t(S) S’: {(№ зачетной книжки: 100), (Фамилия: ‘Иванов’)};

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

Оглавление книги

Тест

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

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

Подсказка: Используйте колонку «Пример» в таблице приоритета и ассоциативности операций, чтобы определить, является ли оператор (имеет один операнд) или бинарным (имеет два операнда).

Например:

Бинарный оператор имеет более высокий приоритет, чем оператор или , поэтому он выполняется первым: . Затем выполняется бинарный оператор , так как он имеет более высокий приоритет, чем оператор .

Ответ: .

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

Задания:

   Выражение №1:

   Выражение №2:

   Выражение №3:

   Выражение №4:

Ответ

Выражение №1:

Уровень приоритета бинарного оператора выше, чем оператора , поэтому: . Ассоциативность бинарного оператора слева направо, поэтому ответ: .

Выражение №2:

Ассоциативность бинарного оператора справа налево, поэтому ответ: .

Выражение №3:

Унарный оператор имеет наивысший приоритет, поэтому: . Затем идет бинарный оператор , поэтому ответ: .

Выражение №4:

Бинарный оператор имеет приоритет выше, чем , поэтому: . Ассоциативность бинарного оператора слева направо, поэтому ответ: .

Не всё может быть перегружено через методы класса

На уроке о перегрузке операторов ввода и вывода мы перегружали оператор вывода для класса Point через дружественную функцию:

#include <iostream>

class Point
{
private:
double m_x, m_y, m_z;

public:
Point(double x=0.0, double y=0.0, double z=0.0): m_x(x), m_y(y), m_z(z)
{
}

friend std::ostream& operator<< (std::ostream &out, const Point &point);
};

std::ostream& operator<< (std::ostream &out, const Point &point)
{
// Поскольку operator<<() является другом класса Point, то мы имеем доступ к закрытым членам Point
out << «Point(» << point.m_x << «, » << point.m_y << «, » << point.m_z << «)»;

return out;
}

int main()
{
Point point1(5.0, 6.0, 7.0);

std::cout << point1;

return 0;
}

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
26
27
28
29
30
31

#include <iostream>

classPoint

{

private

doublem_x,m_y,m_z;

public

Point(doublex=0.0,doubley=0.0,doublez=0.0)m_x(x),m_y(y),m_z(z)

{

}

friendstd::ostream&operator<<(std::ostream&out,constPoint&point);

};

std::ostream&operator<<(std::ostream&out,constPoint&point)

{

// Поскольку operator<<() является другом класса Point, то мы имеем доступ к закрытым членам Point

out<<«Point(«<<point.m_x<<«, «<<point.m_y<<«, «<<point.m_z<<«)»;

returnout;

}

intmain()

{

Point point1(5.0,6.0,7.0);

std::cout<<point1;

return;

}

Однако через метод класса перегрузить оператор мы не сможем. Почему? Потому что при перегрузке через метод класса в качестве левого операнда используется текущий объект. В этом случае левым операндом является объект типа std::ostream. std::ostream является частью Cтандартной библиотеки C++. Мы не можем использовать std::ostream в качестве левого неявного параметра, на который бы указывал скрытый указатель *this, так как указатель *this может указывать только на текущий объект текущего класса, члены которого мы можем изменить, поэтому перегрузка оператора должна осуществляться через дружественную функцию.

Аналогично, хотя мы можем перегрузить через метод класса (как мы делали выше), мы не можем перегрузить через метод класса, поскольку int теперь является левым операндом, на который указатель *this указывать не может.

Перегрузка операторов через методы класса не используется, если левый операнд не является классом (например, int), или это класс, который мы не можем изменить (например, std::ostream).

Приоритет

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

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

В таблице ниже перечислены приоритеты операторов в порядке убывания.

Приоритет
** (экспонента)
~ (Дополнение к единицам)
*, /, //, % (Умножение, Деление, Операторы Модуля)
+, – (Сложение, Вычитание)
<<, >> (операторы сдвига вправо и влево)
& (побитовый AND)
|, ^ (побитовый OR, XOR)
==, !=, >, <, >=, <= (сравнения)
=, +=, -=, *=, /=, //=, %= (присваивания)
is, is not (идентификации)
in, not in (принадлежности)
not, and, or (логические)

Условный тернарный оператор вычисляется как выражение

Стоит отметить, что условный оператор вычисляется как выражение, в то время как ветвление if/else обрабатывается как набор стейтментов. Это означает, что тернарный оператор может быть использован там, где if/else применить невозможно, например, при инициализации константы:

bool inBigClassroom = false;
const int classSize = inBigClassroom ? 30 : 20;

1
2

boolinBigClassroom=false;

constintclassSize=inBigClassroom?3020;

Здесь нельзя использовать if/else, так как константы должны быть инициализированы при объявлении, а стейтмент не может быть значением для инициализации.

Правила перегрузки операций

  • Язык C++ не допускает определения для операций нового лексического символа, кроме уже определенных в языке. Например, нельзя определить в качестве знака операции @.
  • Не допускается перегрузка операций для встроенных типов данных. Нельзя, например, переопределить операцию сложения целых чисел:

    int operator +(int i, int j);

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

class String{  …public:  String operator + (const String &);  …};

class String{  …public:  friend String operator +(String &, String &);  …};

Таблица приоритета и ассоциативности операций

Несколько примечаний:

   1 означает самый высокий уровень приоритета, а 17 — самый низкий. Операции с более высоким уровнем приоритета выполняются первыми.

    означает слева направо.

    означает справа налево.

Ассоциативность Оператор Описание Пример
1. Нет :: Глобальная область видимости (унарный) ::name
:: Область видимости класса (бинарный) class_name::member_name
2. L -> R () Круглые скобки (expression)
() Вызов функции function_name(parameters)
() Инициализация type name(expression)
{} uniform-инициализация (C++11) type name{expression}
type() Конвертация типа new_type(expression)
type{} Конвертация типа (C++11) new_type{expression}
[] Индекс массива pointer
. Доступ к члену объекта object.member_name
-> Доступ к члену объекта через указатель object_pointer->member_name
++ Пост-инкремент lvalue++
–– Пост-декремент lvalue––
typeid Информация о типе во время выполнения typeid(type) or typeid(expression)
const_cast Cast away const const_cast(expression)
dynamic_cast Type-checked cast во время выполнения dynamic_cast(expression)
reinterpret_cast Конвертация одного типа в другой reinterpret_cast(expression)
static_cast Type-checked cast во время компиляции static_cast(expression)
3. R -> L + Унарный плюс +expression
Унарный минус -expression
++ Пре-инкремент ++lvalue
–– Пре-декремент ––lvalue
! Логическое НЕ (NOT) !expression
~ Побитовое НЕ (NOT) ~expression
(type) C-style cast (new_type)expression
sizeof Размер в байтах sizeof(type) or sizeof(expression)
& Адрес &lvalue
* Разыменование *expression
new Динамическое выделение памяти new type
new[] Динамическое выделение массива new type
delete Динамическое удаление памяти delete pointer
delete[] Динамическое удаление массива delete[] pointer
4. L -> R ->* Member pointer selector object_pointer->*pointer_to_member
.* Member object selector object.*pointer_to_member
5. L -> R * Умножение expression * expression
Деление expression / expression
% Деление с остатком expression % expression
6. L -> R + Сложение expression + expression
Вычитание expression — expression
7. L -> R << Побитовый сдвиг влево expression << expression
>> Побитовый сдвиг вправо expression >> expression
8. L -> R < Сравнение: меньше чем expression < expression
<= Сравнение: меньше чем или равно expression <= expression
> Сравнение: больше чем expression > expression
>= Сравнение: больше чем или равно expression >= expression
9. L -> R == Равно expression == expression
!= Не равно expression != expression
10. L -> R & Побитовое И (AND) expression & expression
11. L -> R ^ Побитовое исключающее ИЛИ (XOR) expression ^ expression
12. L -> R | Побитовое ИЛИ (OR) expression | expression
13. L -> R && Логическое И (AND) expression && expression
14. L -> R || Логическое ИЛИ (OR) expression || expression
15. R -> L ?: Тернарный условный оператор expression ? expression : expression
= Присваивание lvalue = expression
*= Умножение с присваиванием lvalue *= expression
/= Деление с присваиванием lvalue /= expression
%= Деление с остатком и с присваиванием lvalue %= expression
+= Сложение с присваиванием lvalue += expression
-= Вычитание с присваиванием lvalue -= expression
<<= Присваивание с побитовым сдвигом влево lvalue <<= expression
>>= Присваивание с побитовым сдвигом вправо lvalue >>= expression
&= Присваивание с побитовой операцией И (AND) lvalue &= expression
|= Присваивание с побитовой операцией ИЛИ (OR) lvalue |= expression
^= Присваивание с побитовой операцией «Исключающее ИЛИ» (XOR) lvalue ^= expression
16. R -> L throw Генерация исключения throw expression
17. L -> R , Оператор Запятая expression, expression

Некоторые операторы вы уже знаете из предыдущих уроков: , , , , , , и . Их значения одинаковы как в математике, так и в языке C++.

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

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

Тест

Задание №1

Вычислите результат следующего выражения: .

Ответ №1

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

Ответ: 8.

Задание №2

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

Подсказка: Используйте ветвление if и оператор сравнения ().

Ответ №2

#include <iostream>

bool isEven(int x)
{
// Если x % 2 == 0, то x — это чётное число
return (x % 2) == 0;
}

int main()
{
std::cout << «Enter an integer: «;
int x;
std::cin >> x;

if (isEven(x))
std::cout << x << » is even\n»;
else
std::cout << x << » is odd\n»;

return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#include <iostream>

boolisEven(intx)

{

// Если x % 2 == 0, то x — это чётное число

return(x%2)==;

}

intmain()

{

std::cout<<«Enter an integer: «;

intx;

std::cin>>x;

if(isEven(x))

std::cout<<x<<» is even\n»;

else

std::cout<<x<<» is odd\n»;

return;

}

Возможно, вы хотели написать или написали функцию isEven() следующим образом:

bool isEven(int x)
{
if ((x % 2) == 0)
return true;
else
return false;
}

1
2
3
4
5
6
7

boolisEven(intx)

{

if((x%2)==)

returntrue;

else

returnfalse;

}

Хотя этот способ тоже рабочий, но он сложнее. Посмотрим, как его можно упростить. Во-первых, давайте вытащим условие if и присвоим его отдельной переменной типа bool:

bool isEven(int x)
{
bool isEven = (x % 2) == 0;
if (isEven) // isEven — true
return true;
else // isEven — false
return false;
}

1
2
3
4
5
6
7
8

boolisEven(intx)

{

boolisEven=(x%2)==;

if(isEven)// isEven — true

returntrue;

else// isEven — false

returnfalse;

}

В коде, приведенном выше, если переменная имеет значение , то возвращаем , в противном случае (если имеет значение ) — возвращаем . Мы же можем сразу возвращать :

bool isEven(int x)
{
bool isEven = (x % 2) == 0;
return isEven;
}

1
2
3
4
5

boolisEven(intx)

{

boolisEven=(x%2)==;

returnisEven;

}

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

bool isEven(int x)
{
return (x % 2) == 0;
}

1
2
3
4

boolisEven(intx)

{

return(x%2)==;

}

Оператор Запятая

Оператор Запятая (или «оператор Comma») позволяет обрабатывать несколько выражений (в то время, когда, обычно, позволяется только одно).

Оператор Символ Пример Операция
Запятая , x, y Вычисляется x, затем вычисляется y, а затем возвращается значение y

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

int x = 0;
int y = 2;
int z = (++x, ++y); // инкремент переменных x и y

1
2
3

intx=;

inty=2;

intz=(++x,++y);// инкремент переменных x и y

Переменной будет присвоен результат вычисления (правого операнда), что равно .

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

int x = 0;
int y = 2;
++x;
++y;
int z = y;

1
2
3
4
5

intx=;

inty=2;

++x;

++y;

intz=y;

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

z = (a, b); // сначала вычисляется выражение (a, b), которое равняется значению b, а затем результат присваивается переменной z
z = a, b; // вычисляется как «(z = a), b», поэтому переменной z присваивается значение a, переменная b — игнорируется

1
2

z=(a,b);// сначала вычисляется выражение (a, b), которое равняется значению b, а затем результат присваивается переменной z

z=a,b;// вычисляется как «(z = a), b», поэтому переменной z присваивается значение a, переменная b — игнорируется

Большинство программистов не используют оператор Comma вообще (разве что только в циклах for).

Обратите внимание, запятая, которая используется в вызовах функций, не является оператором Comma:

int sum = add(x, y); // эта запятая не является оператором Comma

1 intsum=add(x,y);// эта запятая не является оператором Comma

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

int x(3), y(5); // эта запятая не является оператором Comma

1 intx(3),y(5);// эта запятая не является оператором Comma

Правило: Избегайте использования оператора Comma (исключением являются циклы for).

Операция instanceof

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

Java

obj1 instanceof A

1 obj1 instanceofA

Возвращается
true, если
obj1  не
null  и является экземпляром класса
A  или экземпляром дочернего класса
A  или экземпляром класса, реализующего интерфейс
A.

Java

Object obj1 = new String(«test1»);
if (obj1 instanceof String) {
System.out.println(«YES»);
}

1
2
3
4

Objectobj1=newString(«test1»);

if(obj1 instanceofString){

System.out.println(«YES»);

}

Если левый операнд равен
null, то результатом будет
false. Код ниже выведет “NO”:

Java

Object obj1 = null;
if (obj1 instanceof String) {
System.out.println(«YES»);
} else {
System.out.println(«NO»);
}

1
2
3
4
5
6

Objectobj1=null;

if(obj1 instanceofString){

System.out.println(«YES»);

}else{

System.out.println(«NO»);

}

Правила выбора места определения операторных функций

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

Из приведенного общего правила есть достаточно много исключений. Рассмотрим их. Для перегрузки оператора = (присваивание), составных операторов присваивания (+=, *=

и т. д.), оператора [] (индексация), оператора () (вызов функции) и оператора ->(выбор элемента или метода через указатель) можно использовать толькофункции-членыкласса. Это гарантирует, что их первый операнд будет lvalue (ссылкой на объект класса либо самим объектом).

Для перегрузки операторов преобразования объекта класса к другим типам(операторы преобразования типа) также необходимо применять только функции-членыэтого класса.

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

Далее в лекции на примере простого класса комплексных чисел(class Complex) будут

Присвоение с выполнением другой операции

Операции 
+= (сложение с присвоением),
-= (вычитание с присвоением), 
*= (умножение с присвоением),
/= (деление с присвоением),
%= (взятие остатка с присвоением),
&= (битовый И с присвоением),
^=  (битовое исключающее ИЛИ с присвоением),
|= (битовое ИЛИ с присвоением),
<<= (сдвиг влево с присвоением),
>>= (знаковый сдвиг вправо с присвоением),
>>>=  (беззнаковый сдвиг вправо с присвоением) позволяют сразу выполнить операции и присвоить результат другой переменной.

Они работают так:

Java

E1 compop E2

1 E1 compop E2

эквивалентно

Java

E1 = (T) E1 op E2;

1 E1=(T)E1 op E2;

, где
T  — это тип переменной
E1.

То есть
intx1+=x2 эквивалентно
intx1=(int)x1+x2.

Main.java

Java

class Main {
public static void main(String[] args) {
int x1 = 100;
byte x2 = 100;
int x3 = 100;

x1 += 300; // эквивалентно x1 = (int) x1 + 300;
x2 += 300; // эквивалентно x2 = (byte) x2 + 300;
x3 += 300.1; // эквивалентно x3 = (int) x3 + 300.1;

System.out.println(«x1=» + x1); // 400
System.out.println(«x2=» + x2); // -112
System.out.println(«x3=» + x3); // 400
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

classMain{

publicstaticvoidmain(Stringargs){

intx1=100;

bytex2=100;

intx3=100;

x1+=300;// эквивалентно x1 = (int) x1 + 300;

x2+=300;// эквивалентно x2 = (byte) x2 + 300;      

x3+=300.1;// эквивалентно x3 = (int) x3 + 300.1;

System.out.println(«x1=»+x1);// 400

System.out.println(«x2=»+x2);// -112

System.out.println(«x3=»+x3);// 400

}

}

Операторы

Последним пазлом в выражениях являются операторы. С их помощью мы можем объединить операнды для получения нового значения. Например, в выражении , является оператором. С помощью мы объединили операнды и для получения нового значения ().

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

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

Операторы бывают трёх типов:

   Унарные. Работают с одним операндом. Например, оператор (минус). В выражении , оператор применяется только к одному операнду (), чтобы создать новое значение ().

   Бинарные. Работают с двумя операндами (левым и правым). Например, оператор . В выражении , оператор работает с левым операндом () и правым (), чтобы создать новое значение ().

   Тернарные. Работают с тремя операндами (в языке C++ есть только один ).

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

Условный тернарный оператор

Условный (тернарный) оператор (обозначается как ) является единственным тернарным оператором в языке С++, который работает с 3-мя операндами. Из-за этого его часто называют просто «тернарный оператор».

Оператор Символ Пример Операция
Условный ?: c ? x : y Если c — ненулевое значение (true), то вычисляется x, в противном случае — y

Оператор предоставляет сокращенный способ (альтернативу) ветвления if/else.

Стейтменты if/else:

Можно записать как:

Обратите внимание, операнды условного оператора должны быть выражениями (а не стейтментами). Например, ветвление if/else, которое выглядит следующим образом:

Например, ветвление if/else, которое выглядит следующим образом:

Можно записать как:

Большинство программистов предпочитают последний вариант, так как он читабельнее.

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

if (x > y)
larger = x;
else
larger = y;

1
2
3
4

if(x>y)

larger=x;

else

larger=y;

Или вот так:

larger = (x > y) ? x : y;

1 larger=(x>y)?xy;

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

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

Например, для вывода или , мы можем сделать следующее:

if (x > y)
std::cout << x;
else
std::cout << y;

1
2
3
4

if(x>y)

std::cout<<x;

else

std::cout<<y;

Или с помощью тернарного оператора:

std::cout << ((x > y) ? x : y);

1 std::cout<<((x>y)?xy);

Давайте рассмотрим, что произойдет, если мы не заключим в скобки весь условный оператор в вышеприведенном случае. Поскольку оператор имеет более высокий приоритет, чем оператор , то следующий стейтмент (где мы не заключили весь тернарный оператор в круглые скобки, а только лишь условие):

std::cout << (x > y) ? x : y;

1 std::cout<<(x>y)?xy;

Будет обрабатываться как:

(std::cout << (x > y)) ? x : y;

1 (std::cout<<(x>y))?xy;

Таким образом, в консольном окне мы увидим (true), если , в противном случае — выведется (false).

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

Условный тернарный оператор — это удобное упрощение ветвления if/else, особенно при присваивании результата переменной или возврате определенного значения. Но его не следует использовать вместо сложных ветвлений if/else, так как в таких случаях читабельность кода резко ухудшается и вероятность возникновения ошибок только растет.

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

Преобразование в числа

Функция преобразует значения по следующим правилам:

  • Логические значения и преобразуются в и соответственно.
  • Числа возвращаются без изменения.
  • Значение преобразуется в .
  • Значение преобразуется в .

Для строк действуют особые правила:

  • Если строка содержит только цифры с начальным знаком или либо без знака, она всегда преобразуется в целое десятичное число. Начальные нули игнорируются, например «0011» преобразуется в 11.
  • Если строка представляет собой число с плавающей точкой с начальным знаком + или — либо без знака, она преобразуется в соответствующее число с плавающей точкой (начальные нули также игнорируются).
  • Если строка представляет собой число в шестнадцатеричном формате, она преобразуется в соответствующее целое десятичное число.
  • Если строка пустая, она преобразуется в .
  • Если строка содержит что-то отличное от предыдущих вариантов, она преобразуется в .
  • Для объектов вызывается метод , а возвращаемое им значение автоматически преобразуется по предыдущим правилам. Если это преобразование даёт в результате , вызывается метод и применяются правила преобразования строк в числа.

Унарные операторы и работают по тем же правилам, что и функция .

Тернарная операция

Операция «?:» называется тернарной, потому что он принимает три операнда.

<выражение_boolean> ? <выражение1> : <выражение2>

1 <выражение_boolean> ? <выражение1> : <выражение2>

Тернарная операция вычисляет
<выражение_boolean>, если оно равно
true, то вычисляет и возвращает
<выражение1>, а если
false, то
<выражение2> .

Java

class Main {
public static void main(String[] args) {
int x = 3 > 2 ? 5 : -3; // 5
String str1 = 3 == 2 ? «YES»: «NO»; //»NO»
System.out.println(x);
System.out.println(str1);
}
}

1
2
3
4
5
6
7
8

classMain{

publicstaticvoidmain(Stringargs){

intx=3>2?5-3;// 5

Stringstr1=3==2?»YES»»NO»;//»NO»

System.out.println(x);

System.out.println(str1);

}

}

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

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

Adblock
detector