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

Краткое содержание

Арифметическое выражение вычисляется не слева направо, как оно читается, а по скрытой структуре, своему дереву, которую задают приоритет операторов, их ассоциативность и скобки; и в каждом узле этого дерева тип операндов решает, какая операция выполняется, так что 7 / 2 равно 3, а 7 / 2.0 равно 3.5. В этом уроке изучаются пять арифметических операторов C++ с целыми и вещественными числами; целочисленное деление и остаток, которые начиная с C++11 округляют к нулю, откуда следует, что остаток принимает знак делимого и отличается от остатка евклидова деления, когда делимое отрицательно; способ получить евклидов остаток; дерево выражения; тип результата, когда операнды имеют разные типы, и два случая, в которых целочисленное арифметическое выражение теряет смысл: деление на ноль и переполнение в промежуточном вычислении.

Цели обучения

  1. Вычислять частное и остаток целочисленного деления в C++, в том числе с отрицательными операндами, и связывать их с частным и остатком евклидова деления.
  2. Строить дерево арифметического выражения по приоритету и ассоциативности и вычислять его значение.
  3. Предсказывать тип результата операции над операндами разных типов.
  4. Применять целочисленное деление и остаток для разложения величин: цифры числа, длительность в часах и минутах, день недели.

Арифметические операторы

В C++ пять бинарных арифметических операторов: сложение +, вычитание -, умножение *, деление / и остаток %; кроме того, есть унарный минус, который меняет знак своего единственного операнда, как в -x, и унарный плюс, +x, который оставляет его как есть. Первые четыре применяются к целым и к вещественным числам, а остаток только к целым. Однако одна и та же запись не во всех случаях обозначает одну и ту же операцию: если оба операнда / целые, деление целочисленное и его результат есть целое число, частное без дробной части; если хотя бы один из них вещественный, деление вещественное. Урок Символы, логические значения, преобразования и константы показал самое заметное следствие этого правила: double r{7 / 2}; сохраняет 3, потому что деление выполнилось над целыми раньше, чем результат преобразовался в вещественное число.

ПримерПять операторов с двумя целыми числами

Программа применяет пять операторов к 17 и 5 и повторяет деление с вещественным делимым.

Программа на C++
#include <print>​int main(){    const int a{17};    const int b{5};    std::println("{} + {} = {}", a, b, a + b);    std::println("{} - {} = {}", a, b, a - b);    std::println("{} * {} = {}", a, b, a * b);    std::println("{} / {} = {}", a, b, a / b);    std::println("{} % {} = {}", a, b, a % b);    const double x{17.0};    std::println("{} / {} = {}", x, b, x / b);}
Вывод
17 + 5 = 2217 - 5 = 1217 * 5 = 8517 / 5 = 317 % 5 = 217 / 5 = 3.4

17, делённое на 5, даёт 3, и 2 остаётся: это частное и остаток при раскладывании 17 предметов на группы по 5. Последняя строка делит вещественное число на целое и получает 3.4. Следует заметить, что std::println выводит вещественное 17.0 как «17»: пустой заполнитель выводит кратчайшее представление значения, так что по выведенному тип не виден; чтобы его увидеть, запрашивают знаки после запятой с помощью {:.1f}.

Оператор % не допускает вещественных операндов. Запись 7.5 % 2 есть не логическая ошибка, которую программа обнаружит при выполнении, а ошибка компиляции: компилятор сообщает, что операнды типов double и int недопустимы для этого оператора.

Программа на C++
#include <print>​int main(){    std::println("{}", 7.5 % 2);}
Сообщения компилятора об ошибках
main.cpp: In function ‘int main()’:main.cpp:5:28: error: invalid operands of types ‘double’ and ‘int’ to binary ‘operator%’    5 |     std::println("{}", 7.5 % 2);      |                        ~~~ ^ ~

Остаток вещественного деления существует, и его вычисляет функция std::fmod из заголовочного файла <cmath>, которая будет изучаться в уроке Биты и математическая библиотека вместе с возведением в степень: в C++ нет оператора возведения в степень, и 2 ^ 3 равно не 8, а кое-чему другому, что будет объяснено там.