5.3 – Остаток от деления и возведение в степень
Оператор остатка от деления
Оператор остатка от деления – это оператор, который возвращает остаток после целочисленного деления. Например, 7/4 = 1 и остаток 3. Следовательно, 7 % 4 = 3. В качестве другого примера, 25/7 = 3 и остаток 4, таким образом, 25 % 7 = 4. Оператор остатка от деления работает только с целочисленными операндами.
Этот оператор наиболее полезен для проверки того, делится ли одно число без остатка на другое число: если x % y
принимает значение 0, то мы знаем, что x
без остатка делится на y
.
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int x{};
std::cin >> x;
std::cout << "Enter another integer: ";
int y{};
std::cin >> y;
std::cout << "The remainder is: " << x % y << '\n';
if ((x % y) == 0)
std::cout << x << " is evenly divisible by " << y << '\n';
else
std::cout << x << " is not evenly divisible by " << y << '\n';
return 0;
}
Вот результаты нескольких запусков этой программы:
Enter an integer: 6
Enter another integer: 3
The remainder is: 0
6 is evenly divisible by 3
Enter an integer: 6
Enter another integer: 4
The remainder is: 2
6 is not evenly divisible by 4
Теперь давайте рассмотрим пример, в котором второе число больше первого:
Enter an integer: 2
Enter another integer: 4
The remainder is: 2
2 is not evenly divisible by 4
Поначалу остаток от 2 может быть немного неочевидным, но это просто: 2/4 равно 0 (с использованием целочисленного деления), остаток 2. Когда второе число больше первого, второе число разделит первое число на 0 раз, поэтому первое число будет остатком.
Остаток от деления с отрицательными числами
Оператор остатка от деления также может работать с отрицательными операндами. x % y
всегда возвращает результаты со знаком x
.
Запускаем приведенную выше программу:
Enter an integer: -6
Enter another integer: 4
The remainder is: -2
-6 is not evenly divisible by 4
Enter an integer: 6
Enter another integer: -4
The remainder is: 2
6 is not evenly divisible by -4
В обоих случаях вы можете видеть, что остаток принимает знак первого операнда.
Предупреждение
До C++11 оператор остатка от деления с отрицательным операндом мог давать как положительный, так и отрицательный результат. В C++11 это стало предсказуемым.
Где оператор возведения в степень?
Вы заметите, что оператор ^
(обычно используемый для обозначения возведения в степень в математике) – в C++ это побитовая операция XOR (исключающее ИЛИ) (описанная в уроке «O.3 – Битовые манипуляции с побитовыми операторами и битовыми масками»). В C++ нет оператора возведения в степень.
Чтобы выполнить возведение в степень в C++, включите с помощью #include
заголовочный файл <cmath> и используйте функцию pow()
:
#include <cmath>
double x{ std::pow(3.0, 4.0) }; // 3 в 4-й степени
Обратите внимание, что параметры (и возвращаемое значение) функции pow()
имеют тип double
. Из-за ошибок округления в числах с плавающей запятой результаты pow()
могут быть неточными (даже если вы передадите ей целочисленные значения или целые числа).
Если вы хотите выполнить целочисленное возведение в степень, лучше всего использовать для этого свою собственную функцию. Следующая функция реализует целочисленное возведение в степень (с использованием для повышения эффективности неинтуитивного алгоритма «возведения в возведения в квадрат»):
#include <cstdint> // for std::int_fast64_t
// примечание: exp должно быть неотрицательным
std::int_fast64_t pow(int base, int exp)
{
std::int_fast64_t result{ 1 };
while (exp)
{
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
Не волнуйтесь, если вы не понимаете, как работает эта функция – чтобы вызывать ее, вам не нужно понимать ее внутреннюю работу.
#include <iostream>
#include <cstdint> // для std::int_fast64_t
// примечание: exp должно быть неотрицательным
std::int_fast64_t powint(int base, int exp)
{
std::int_fast64_t result{ 1 };
while (exp)
{
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
int main()
{
std::cout << powint(7, 12); // 7 в 12-ой степени
return 0;
}
Данная программа выводит следующее:
13841287201
Предупреждение
В подавляющем большинстве случаев целочисленное возведение в степень приведет к переполнению целочисленного типа. Вероятно, именно поэтому такая функция не была включена в стандартную библиотеку.
Небольшой тест
Вопрос 1
Что будет результатом вычисления следующего выражения? 6 + 5 * 4 % 3
Ответ
Поскольку *
и %
имеют более высокий приоритет, чем +
, +
будет вычисляться последним. Мы можем переписать наше выражение как 6 + (5 * 4 % 3)
. Операторы *
и %
имеют одинаковый приоритет, поэтому мы должны учитывать ассоциативность для их вычисления. Ассоциативность для операторов *
и %
– слева направо, поэтому сначала мы вычисляем левый оператор. Мы можем переписать наше выражение так: 6 + ((5 * 4) % 3)
.
6 + ((5 * 4) % 3) = 6 + (20 % 3) = 6 + 2 = 8
Вопрос 2
Напишите программу, которая просит пользователя ввести целое число и сообщает пользователю, четное это число или нечетное. Напишите функцию с именем isEven()
, которая возвращает true
(истину), если переданное ей целое число четное, и false
(ложь) в противном случае. Чтобы проверить, является ли целочисленный параметр четным, используйте оператор остатка от деления.
Подсказка: в этой программе вам нужно будет использовать операторы if
и оператор сравнения (==
). Если вам нужно напомнить, как это сделать, смотрите урок «4.9 – Логические (булевы) значения».
Ваша программа должна давать следующий вывод:
Enter an integer: 5
5 is odd
Ответ
#include <iostream>
bool isEven(int x)
{
// если x % 2 == 0, наше число делится на 2 без остатка,
// что означает, что число должно быть четным
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;
}
Примечание: у вас может возникнуть соблазн написать функцию isEven()
следующим образом:
bool isEven(int x)
{
if ((x % 2) == 0)
return true;
else
return false;
}
Хотя это работает, но это сложнее, чем должно быть. Давайте посмотрим, как это можно упростить. Во-первых, давайте вытащим условное выражение if
и присвоим его отдельному логическому значению:
bool isEven(int x)
{
bool isEvenNumber = (x % 2) == 0;
if (isEvenNumber) // isEvenNumber равно true
return true;
else // isEvenNumber равно false
return false;
}
Теперь обратите внимание, что оператор if
выше, по сути, говорит: «Если isEvenNumber
равно true
, вернуть true
, в противном случае, если isEvenNumber
равно false
, вернуть false
». Если это так, мы можем просто вернуть isEvenNumber
:
bool isEven(int x)
{
bool isEvenNumber = (x % 2) == 0;
return isEvenNumber;
}
И в этом случае, поскольку мы используем переменную isEvenNumber
только один раз, мы могли бы также исключить и ее:
bool isEven(int x)
{
return (x % 2) == 0;
}