Приоритет арифметических операций программирование

Приоритет арифметических операций программирование

Арифметические операции производятся над числами. Значения, которые участвуют в операции, называются операндами. В языке программирования C++ арифметические операции могут быть бинарными (производятся над двумя операндами) и унарными (выполняются над одним операндом). К бинарным операциям относят следующие:

    + Операция сложения возвращает сумму двух чисел:

int a ; int b ; int c ; // 17 int d ; // 11

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

int a ; int b ; int c = a + b; // 17 int d = 4 + b; // 11
int a ; int b ; int c ; // 3 int d ; // -3
int a ; int b ; int c ; // 70 int d ; // 28
int a ; int b ; int c ; // c = 5 int d ; // d = 0

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

#include int main() < int a ; int b ; float c ; // c = 5 double d ; // d = 0 std::cout #include int main() < float a ; int b ; float c ; // c = 5.2 double d ; // d = 0.8 std::cout %

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

int a ; int b ; int c ; // c = 26 % 5 = 26 - 5 * 5 = 1 int d ; // d = 4 % 5 = 4

Некоторые особенности при работе с числами с плавающей точкой

При сложении или вычитании чисел с плавающей точкой, которые сильно отличаются по значению, следует проявлять осторожность. Например, сложим число 1.23E-4 ( 0.000123 ) и 3.65E+6 (3650000). Мы ожидаем, что сумма будет равна 3650000,000123 . Но при преобразовании в число с плавающей запятой с точностью до семи цифр это становится следующим

3.650000E+06 + 1.230000E-04 = 3.650000E+06

Или соответствующий код на С++:

#include int main() < float num1< 1.23E-4 >; // 0.000123 float num2< 3.65E+6 >; // 3650000 float sum ; // sum =3.65e+06 std::cout

То есть первое число никак не изменилось, поскольку для хранения точности отводится только 7 цифр.

Также стоит отметить, что стандарт IEEE, который реализуется компиляторами С++, определяет специальные значения для чисел с плавающей точкой, в которых мантисса на бинарном уровне состоит только из нулей, а экспонента, которая состоит из одних единиц, в зависимости от знака представляет значения +infinity (плюс бесконечность +∞) и -infinity (минус бесконечность -∞). И при делении положительного числа на ноль, результатом будет +infinity , а при делении отрицательного числа на ноль - -infinity .

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

Для демонстрации рассмотрим следующую программу:

#include int main() < double a< 1.5 >, b<>, c<>, d ; double result < a / b >; std::cout  
1.5/0 = inf -1.5/0 = -inf 0/0 = nan nan + 1.5 = nan

Инкремент и декремент

Также есть две унарные арифметические операции, которые производятся над одним числом: ++ (инкремент) и -- (декремент). Каждая из операций имеет две разновидности: префиксная и постфиксная:

    Префиксный инкремент . Увеличивает значение переменной на единицу и полученный результат используется как значение выражения ++x

#include int main() < int a ; int b <++a>; std::cout Постфиксный инкремент.

Увеличивает значение переменной на единицу, но значением выражения x++ будет то, которое было до увеличения на единицу

#include int main() < int a ; int b ; std::cout Префиксный декремент.

Уменьшает значение переменной на единицу, и полученное значение используется как значение выражения --x

#include int main() < int a ; int b ; std::cout Постфиксный декремент.

Уменьшает значение переменной на единицу, но значением выражения x-- будет то, которое было до уменьшения на единицу

#include int main() < int a ; int b ; std::cout левоассоциативными - такие операторы выполняются слева направо и правоассоциативными - выполняются справа налево. Подавляющее большинство операторов левоассоциативны (например, бинарные арифметические операции), поэтому большинство выражений оценивается слева направо. Правоассоциативными операторами являются все унарные операторы, различные операторы присваивания и условный оператор.

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

++ (инкремент), -- (декремент)
* (умножение), / (деление), % (остаток от деления)
+ (сложение), - (вычитание)

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

int a = 8; int b = 7; int c = a + 5 * ++b; // 48

Хотя операции выполняются слева направо, но вначале будет выполняться операция инкремента ++b , которая увеличит значение переменной b и возвратит его в качестве результата, так как эта операция имеет больший приоритет. Затем выполняется умножение 5 * ++b , и только в последнюю очередь выполняется сложение a + 5 * ++b Следует учитывать, что если в одной инструкции для одной переменной сразу несколько раз вызываются операции инкремента и декремента, то результат может быть неопределенным, и много зависит от конкретного компилятора. Например:

int count ; int result = ++count * 3 + count++ * 5;

Так, и g++, и clang++ скомпилируют данный код, и результат переменной result будет таким, как в принципе и ожидается - 16, но компилятор clang++ также сгенерирует предупреждение.

Переопределение порядка операций

Источник

Приоритет арифметических операций программирование

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

В арифметических операциях участвуют числа. В Java есть бинарные арифметические операции (производятся над двумя операндами) и унарные (выполняются над одним операндом). К бинарным операциям относят следующие:

    + операция сложения двух чисел:

int a = 10; int b = 7; int c = a + b; // 17 int d = 4 + b; // 11
int a = 10; int b = 7; int c = a - b; // 3 int d = 4 - a; // -6
int a = 10; int b = 7; int c = a * b; // 70 int d = b * 5; // 35
int a = 20; int b = 5; int c = a / b; // 4 double d = 22.5 / 4.5; // 5.0

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

double k = 10 / 4; // 2 System.out.println(k);

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

double k = 10.0 / 4; // 2.5 System.out.println(k);
int a = 33; int b = 5; int c = a % b; // 3 int d = 22 % 4; // 2 (22 - 4*5 = 2)

Также есть две унарные арифметические операции, которые производятся над одним числом: ++ (инкремент) и -- (декремент). Каждая из операций имеет две разновидности: префиксная и постфиксная:

    ++ (префиксный инкремент) Предполагает увеличение переменной на единицу, например, z=++y (вначале значение переменной y увеличивается на 1, а затем ее значение присваивается переменной z)

int a = 8; int b = ++a; System.out.println(a); // 9 System.out.println(b); // 9
int a = 8; int b = a++; System.out.println(a); // 9 System.out.println(b); // 8
int a = 8; int b = --a; System.out.println(a); // 7 System.out.println(b); // 7
int a = 8; int b = a--; System.out.println(a); // 7 System.out.println(b); // 8

Приоритет арифметических операций

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

++ (постфиксный инкремент), -- (постфиксный декремент)

++ (префиксный инкремент), -- (префиксный декремент)

* (умножение), / (деление), % (остаток от деления)

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

int a = 8; int b = 7; int c = a + 5 * ++b; System.out.println(c); // 48

Вначале будет выполняться операция инкремента ++b , которая имеет больший приоритет - она увеличит значение переменной b и возвратит его в качестве результата. Затем выполняется умножение 5 * ++b , и только в последнюю очередь выполняется сложение a + 5 * ++b

Скобки позволяют переопределить порядок вычислений:

int a = 8; int b = 7; int c = (a + 5) * ++b; System.out.println(c); // 104

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

Ассоциативность операций

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

  • Левоассоциативные операторы, которые выполняются слева направо
  • Правоассоциативные операторы, которые выполняются справа налево

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

Стоит нам трактовать это выражение как (10 / 5) * 2 или как 10 / (5 * 2) ? Ведь в зависимости от трактовки мы получим разные результаты.

Все арифметические операторы (кроме префиксного инкремента и декремента) являются левоассоциативными, то есть выполняются слева направо. Поэтому выражение 10 / 5 * 2 необходимо трактовать как (10 / 5) * 2 , то есть результатом будет 4.

Операции с числами с плавающей точкой

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

double d = 2.0 - 1.1; System.out.println(d);

В данном случае переменная d будет равна не 0.9, как можно было бы изначально предположить, а 0.8999999999999999. Подобные ошибки точности возникают из-за того, что на низком уровне для представления чисел с плавающей точкой применяется двоичная система, однако для числа 0.1 не существует двоичного представления, также как и для других дробных значений. Поэтому в таких случаях обычно применяется класс BigDecimal, который позволяет обойти подобные ситуации.

Источник

C Урок 17. Приоритет операций

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

Уровень прио- ритета Опе-
ратор
Наименование оператора Порядок выполнения
1 ( ) Вызов функции слева направо
[ ] Обращение к массиву по индексу
-> Выбор элемента структуры или объединения по указателю
. Выбор элемента структуры или объединения по ссылке
2 ! Логическое отрицание справа налево
~ Побитовое отрицание
++ Инкрементирование
Декрементирование
+ Унарный плюс
Унарный минус
* Обращение по адресу, разыменовывание
& Взятие адреса
(type) Приведение типа
sizeof Размер
3 * Умножение слева направо
/ Деление
% Деление по модулю
4 + Сложение слева направо
Вычитание
5 >> Сдвиг битов вправо слева направо
Сдвиг битов влево
6 Меньше слева направо
Меньше или равно
> Больше
>= Больше или равно
7 == Равенство слева направо
!= Неравенство
8 & Побитовое И (AND) слева направо
9 ^ Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) слева направо
10 | Побитовое ИЛИ (OR) слева направо
11 && Логическое И слева направо
12 || Логическое ИЛИ слева направо
13 ?: Тернарная операция справа налево
14 = Присваивание справа налево
+= Сложение с присваиванием
-= Вычитание с присваиванием
*= Умножение с присваиванием
/= Деление с присваиванием
%= Деление по модулю с присваиванием
&= Побитовое И с присваиванием
^= Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ с присваиванием
|= Побитовое ИЛИ с присваиванием
< Побитовый сдвиг влево с присваиванием
>>= Побитовый сдвиг вправо с присваиванием
15 , Операция запятая слева направо

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

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

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

Проект сделаем из проекта MYPROG16 прошлого занятия и имя ему было присвоено MYPROG17.

Откроем файл main.c и в функции main(), как обычно, удалим весь код тела кроме возврата нуля, останется от него вот это

return 0 ; //Return an integer from a function

Первый пример кода будет самый простой. Добавим вот такой код в функцию main()

Источник

Читайте также:  Инструменты кроссплатформенной мобильной разработки
Оцените статью