Краткое содержание
Арифметическое выражение вычисляется не слева направо, как оно читается, а по скрытой структуре, своему дереву, которую задают приоритет операторов, их ассоциативность и скобки; и в каждом узле этого дерева тип операндов решает, какая операция выполняется, так что 7 / 2 равно 3, а 7 / 2.0 равно 3.5. В этом уроке изучаются пять арифметических операторов C++ с целыми и вещественными числами; целочисленное деление и остаток, которые начиная с C++11 округляют к нулю, откуда следует, что остаток принимает знак делимого и отличается от остатка евклидова деления, когда делимое отрицательно; способ получить евклидов остаток; дерево выражения; тип результата, когда операнды имеют разные типы, и два случая, в которых целочисленное арифметическое выражение теряет смысл: деление на ноль и переполнение в промежуточном вычислении.
Цели обучения
- Вычислять частное и остаток целочисленного деления в C++, в том числе с отрицательными операндами, и связывать их с частным и остатком евклидова деления.
- Строить дерево арифметического выражения по приоритету и ассоциативности и вычислять его значение.
- Предсказывать тип результата операции над операндами разных типов.
- Применять целочисленное деление и остаток для разложения величин: цифры числа, длительность в часах и минутах, день недели.
Арифметические операторы
В C++ пять бинарных арифметических операторов: сложение +, вычитание -, умножение *, деление / и остаток %; кроме того, есть унарный минус, который меняет знак своего единственного операнда, как в -x, и унарный плюс, +x, который оставляет его как есть. Первые четыре применяются к целым и к вещественным числам, а остаток только к целым. Однако одна и та же запись не во всех случаях обозначает одну и ту же операцию: если оба операнда / целые, деление целочисленное и его результат есть целое число, частное без дробной части; если хотя бы один из них вещественный, деление вещественное. Урок Символы, логические значения, преобразования и константы показал самое заметное следствие этого правила: double r{7 / 2}; сохраняет 3, потому что деление выполнилось над целыми раньше, чем результат преобразовался в вещественное число.
Программа применяет пять операторов к 17 и 5 и повторяет деление с вещественным делимым.
#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.417, делённое на 5, даёт 3, и 2 остаётся: это частное и остаток при раскладывании 17 предметов на группы по 5. Последняя строка делит вещественное число на целое и получает 3.4. Следует заметить, что std::println выводит вещественное 17.0 как «17»: пустой заполнитель выводит кратчайшее представление значения, так что по выведенному тип не виден; чтобы его увидеть, запрашивают знаки после запятой с помощью {:.1f}.
Оператор % не допускает вещественных операндов. Запись 7.5 % 2 есть не логическая ошибка, которую программа обнаружит при выполнении, а ошибка компиляции: компилятор сообщает, что операнды типов double и int недопустимы для этого оператора.
#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, а кое-чему другому, что будет объяснено там.
Загрузка содержимого…