Урок №39. Арифметические операторы

  Юрий  | 

  |

  Обновл. 11 Сен 2021  | 

 238508

 ǀ   64 

На этом уроке мы рассмотрим арифметические операторы и их использование в языке С++.

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

Унарные операторы — это операторы, которые применяются только к одному операнду. Существуют два унарных арифметических оператора: плюс (+) и минус ().

Оператор Символ Пример Операция
Унарный плюс + +x Значение x
Унарный минус −x Отрицательное значение x

Унарный оператор + возвращает значение операнда. Другими словами, +5 = 5 или +х = х. Унарный плюс вам, скорее всего, не придется использовать. Его по большей части добавили в качестве симметрии с унарным оператором минус. Унарный оператор минус возвращает операнд, умноженный на −1. Например, если х = 5, то −х = −5.

Оба этих оператора пишутся непосредственно перед самим операндом, без пробела (−x, а не − x).

Не следует путать унарный оператор минус с бинарным оператором вычитания, хоть они и используют один и тот же символ. Например, в выражении х = 5 − −3;, первый минус — это оператор вычитания, а второй — унарный минус.

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


Бинарные операторы — это операторы, которые применяются к двум операндам (слева и справа). Существует 5 бинарных операторов.

Оператор Символ Пример Операция
Сложение + x + y x плюс y
Вычитание x − y x минус y
Умножение * x * y x умножить на y
Деление / x / y x разделить на y
Деление с остатком % x % y Остаток от деления x на y

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

Деление целых чисел и чисел типа с плавающей точкой

Оператор деления имеет два режима. Если оба операнда являются целыми числами, то оператор выполняет целочисленное деление. Т.е. любая дробь (больше/меньше) отбрасывается и возвращается целое значение без остатка, например, 7 / 4 = 1.

Если один или оба операнда типа с плавающей точкой, то тогда будет выполняться деление типа с плавающей точкой. Здесь уже дробь присутствует. Например, выражения 7.0 / 3 = 2.333, 7 / 3.0 = 2.333 или 7.0 / 3.0 = 2.333 имеют один и тот же результат.

Попытки деления на 0 (или на 0.0) станут причиной сбоя в вашей программе, и это правило не следует забывать!

Использование оператора static_cast в операциях деления


На уроке о символьном типе данных char мы уже использовали оператор static_cast для вывода ASCII-символов в виде целых чисел.

Аналогичным образом мы можем использовать static_cast для конвертации целого числа в число типа с плавающей точкой. Таким образом, вместо целочисленного деления выполнится деление типа с плавающей точкой. Например:

Результат выполнения программы:

int / int = 1
double / int = 1.75
int / double = 1.75
double / double = 1.75

Деление с остатком

Оператор деления с остатком (%) работает только с целочисленными операндами и возвращает остаток от целочисленного деления. Например:

   Пример №1: 7 / 4 = 1 с остатком 3, таким образом, 7 % 4 = 3.

   Пример №2: 25 / 7 = 3 с остатком 4, таким образом, 25 % 7 = 4. Остаток составляет не дробь, а целое число.

   Пример №3: 36 % 5 = 7 с остатком 1. В числе 36 только 35 делится на 5 без остатка, поэтому 36 − 35 = 1, 1 — это остаток и результат.

Данный оператор чаще всего используют для проверки деления без остатка одних чисел на другие. Если х % у == 0, то х делится на у без остатка.

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

Результат выполнения программы:

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 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

О while мы еще поговорим на соответствующем уроке.

Отрицательные числа в операциях деления до C++11


До C++11, если любой из операндов целочисленного деления является отрицательным, то компилятор округляет результат самостоятельно! Например, результатом −5 / 2 может быть либо −3, либо −2. Однако большинство современных компиляторов округляют числа в сторону нуля (например, в −5 / 2 результатом будет −2). В спецификации C++11 определили, что компилятор должен всегда округлять к нулю (или, проще говоря, просто отбрасывать дробь).

Также до C++11, если один из операндов оператора деления с остатком является отрицательным, то результат может быть как положительным, так и отрицательным! Например, результатом −5 % 2 может быть как 1, так и −1. В спецификации C++11 решили сделать так, чтобы результат a % b был того же знака, что и значение а.

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

Оператор Символ Пример Операция
Присваивание = x = y Присваиваем значение y переменной x
Сложение с присваиванием += x += y Добавляем y к x
Вычитание с присваиванием −= x −= y Вычитаем y из x
Умножение с присваиванием *= x *= y Умножаем x на y
Деление с присваиванием /= x /= y Делим x на y
Деление с остатком и с присваиванием %= x %= y Присваиваем остаток от деления x на y переменной x

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

Это работает, но требуется два оператора для выполнения.

Так как стейтменты типа х = х + 5 являются очень распространенными, то C++ предоставляет 5 арифметических операторов присваивания для нашего удобства. Вместо х = х + 5, мы можем записать:

Вместо:

Мы можем записать:

Где оператор возведения в степень?

В языке C++ вместо оператора возведения в степень есть функция pow(), которая находится в заголовочном файле cmath. pow(base, exponent) эквивалентно baseexponent. Стоит отметить, что параметры pow() имеют тип double, поэтому вы можете использовать не только целые числа, но и дробные. Например:

Тест

Задание №1

Вычислите результат следующего выражения: 6 + 5 * 4 % 3.

Ответ №1

Поскольку операторы * и % имеют более высокий приоритет, чем оператор +, то оператор + будет выполняться последним. Мы можем переписать наше выражение следующим образом: 6 + (5 * 4 % 3). Операторы * и % имеют одинаковый приоритет, но их ассоциативность слева направо, так что левый оператор будет выполняться первым. Получается: 6 + ((5 * 4) % 3).

6 + ((5 * 4) % 3) = 6 + (20 % 3) = 6 + 2 = 8

Ответ: 8.

Задание №2

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

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

Ответ №2

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

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

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

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

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (519 оценок, среднее: 4,90 из 5)
Загрузка...

Комментариев: 64

  1. Taras Polishuk:

    Решил так.

  2. Сашуня:

    Второе задание:

  3. Влад:

    Можете, пожалуйста, пояснить как (count % == 0) отвечает за перенос следующей строки, а именно приравнивание к нулю

    1. |Oleg|:

      Просто проверяется каждое число, кратно ли оно двадцати. Если остаток от деления нулевой, значит число делится на двадцать нацело, а выражение (count % 20 == 0) справедливо. Ответ «Да» — и оператор пропускает нас к следующему действию, т.е. переносу строки std::cout << «\n»;     «Нет» — и суда нет. Просто прибавляется счётчик, как будто никакого if не было. Возвращение к началу цикла, но уже с числом, большим на единицу. И так 100 раз, из которых имеем 5 случаев числа кратного 20 = 5 переносов строки.

  4. Sergey:

    Здравствуйте… очень нравится Ваш курс!
    Такая запись приемлема или лучше как можно реже использовать тернарные операторы?

  5. Максим:

    9 строк кода:

    1. Михаил:

      Для использования рекурсивных функций надо разбираться в памяти. 9 строк такого кода могут использовать больше памяти чем в другом решении. Плюс рекурсивная функция выполнятеся по времени дольше….

  6. A.Stein:

  7. LiSteNight:

    Получилось очень коротко, по сравнению с другими решениями. Программа работает, но правильно ли я сделал?

  8. Петр:

    1. Фото аватара Юрий:

      Крутое вступление)

      1. Петр:

        Благодарю, Юрий! С детства любил читать книги по программированию… :-D. Читаю следующие главы и вижу, что в листинге можно кое-что оптимизировать (например, поменять i++ на ++i в циклах for…)
        Добра и удачи!

        1. Фото аватара Юрий:

          Пожалуйста 🙂 И Вам добра и удачи!)

    2. Петр:

      Заметил, что в листинге присутствует изменение типа значения функции <bool isEven(int number)> при передаче его в качестве аргумента функции <void printResult(int result)>… причём в самой функции <void printResult(int result)> происходит обратное преобразование в тип bool. Бывает… %-).

  9. ОЛЕГ-777:

    Задание №2:

    Просто обожаю С++!!! Он мощный и красивый!

  10. Раф:

    Я сделал проще

    1. Владимир:

      Оно проще, согласен. Но в задании требуется написать функция isEven().

    2. Макс:

      Перепутал / с %.

  11. Dima:

    Как-то так получилось

  12. AHTOH:

    Вроде работает:

  13. Slava:

    Решение задачи

    "ifn.h"

    main.cpp

  14. Виктор:

    Отошёл от пункта спецификации, где "Напишите функцию isEven(), которая возвращает true" и упростил программу 🙂

  15. Эдуард:

    Моё решение на тест 2:

  16. Sagynysh:

    вот такой вот вариантчик

  17. Владимир:

    Все понял, каюсь и благодарю. Это ж целочисленный формат, епт… Незнаю чего так тупанул в таком простом моменте. Что поделать. Бывает.

    1. Фото аватара Юрий:

      Ничего страшного, это естественно в процессе изучения чего-либо. Главное — двигаться дальше)

  18. Владимир:

    Есть вопрос. В разделе "Отрицательные числа в операциях деления до C++11" есть такой фрагмент :
    "… до C++11…результатом −5 % 2 может быть как 1, так и −1…"
    Но как??? Может как 5 так и -5? Откуда там еденица?

    1. Дмитрий:

      Прежде чем писать комментарий вы бы перечитали весь материал лучше… Деление с остатком не есть деление: 7%4=3; 6%4=2; 5%4=1; 4%4=0.

      1. владимир:

        Ну правильно все пишете. А 5/2 сколько будет? Правильно, 2.5. Какой остаток дробный видим? Правильно, 0.5. Так что должно быть результатом выражения 5%2 по вышеприведенной вами же логике? Не 5, нет? Откуда 1?

        1. Фото аватара Юрий:

          Владимир, перечитайте урок ещё раз и посмотрите информацию в Интернете по поводу оператора % (остаток от деления). 5%2=1 от того, что 2*2=4 и 5-4=1.

        2. Дмитрий:

          Спешу вас удивить владимир, но
          5 / 2 = 2! а уже 5.0 / 2 или 5 / 2.0 или 5.0 / 2.0 вот тогда ровняется 2.5. Ибо int / int = int! И советую я вам перечитать внимательно не только это урок но и главу 2 (в частности уроки 31, 32, и 33). Да и привыкайте разбираться сами, ибо путь этот тернист подводными камнями 😉

        3. Борис:

          Владимир, кто вам сказал, что остаток от деления — это то что после десятичной точки? Тут и есть ваша ошибка.

  19. Юрий:

    Я написал без применения функции. Но с проблемой — компьютер отвечает с запозданием. Писалось в Eclipse IDE, Manjaro Linux.

  20. Алексей:

    Даже не знаю как я мог не понять эти деления, но было ясно насчет if.
    Буль можно использовать, но как поставил Ваш вариант — подумал, зачем.

    Не знаю кому проще или сложнее, но вроде бы проще уже некуда.

    1. Danger:

      Неудобно только то, что у вас многие стейтменты в одну строчку.

  21. Кирилл:

  22. Дмитрий:

  23. Вячеслав:

    Вот мой вариант. Юрий посмотрите и скажите свое мнение.

  24. Andrey:

    По примеру задачки из итогового теста (если точней, то по примеру вашего решения) — сделал вот так.
    Попробовал — работает.
    Посмотрел ваше решение тут — узнал опять много нового 🙂
    Например то, что при инициализации переменной можно делать вот так

    (почему-то не подумал бы, что проверка == будет работать при инициализации тоже).
    А вот то, что return может и сам посчитать — уже знал, но забыл 🙁 Так бы сразу через него и сделал, но получилось вообще через if о_О

    Кстати по прошлым примерам, когда мы все действия запихивали каждое в свою ф-цию, сделал всю программу на сколько смог. Пытался и последний if впихнуть, но с ним что-то не захотело… 🙂 Только вот может в больших программах это и имеет смысл, но вот в таких — кажется излишне громоздким и не нужным. Ваш пример здесь намного удобней и красивей смотрится.
    Кстати вопрос.
    Задачки — тоже с источника, или сами делаете?)

  25. Андрей:

    Решил сделать вот так, надеюсь, что правильно.

  26. Andrey:

    немного упростил IsEven

    1. danila:

      Андрюха, ты лучший!

  27. Алексей:

  28. Dennis:

    У меня вопрос, а зачем вот так расписывать, когда , если нам нужно вывести просто результат ?

    Если только для подачи материала ? если так — то гуд.

    1. Saturn21:

      Согласен. Но:
      please ENTRE number
      Эммм… вы француз? ))
      (Я знаю, что E и R находятся рядом, но это смешно)

  29. SuRprizZe:

    Думаю это ,не плохое решение.

    1. Фото аватара Юрий:

      Плохое. Одна функция должна выполнять одну задачу. У вас все задачи выполняет одна функция.

      1. Алексей:

        И красивее будет, если setlocale(LC_ALL, "ru"); Без нее сейчас как без рук. Для понимания лучше.

      2. Алексей:

        И вот вопрос: при вводе 5, сообщается о нечетности. А при вводе 5.5… тоже сообщается о нечетности)))) почему? Переменная int.

        1. Фото аватара Юрий:

          Потому что любая дробь отбрасывается, а не округляется. Будь у вас 5.99 — эта дробь отбросится и останется 5.

    2. Alexey:

      А еще функция должна возвращать значение bool, а возвращает int.

      1. ХейЛонг:

        Это не проблема, на самом деле, тут вообще не было разницы, какой тип функции. Её можно было сделать void, и просто выполнить. Но меня заинтересовало, что она выводит в cout, если на возврат ставится введённое пользователем число. Вполне ожидаемо, что ненулевое значение трансформировалось в логическую единицу. Так что сюрпризу спасибо за интересный эксперимент.

  30. Максим:

    Я так сделал

    1. Фото аватара Юрий:

      Хорошее решение, действительно.

    2. somebox:

      У меня похожий вариант:

      Не понимаю, зачем использовать с bool. По мне, это усложняет код.

      1. Saturn21:

        Сетлокейл не забываем ))

      2. Дмитрий:

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

        1. Фото аватара Юрий:

          Именно!

      3. ХейЛонг:

        Усложнение простого кода поможет в будущем упростить сложный код. Парадоксально немного, но так оно и работает. Тяжело в учении — легко в бою)

  31. Ka4:

    так можно же?)

    1. Фото аватара Юрий:

      Да, можно и так. Как вариант.

    2. Александр:

      Возвращение к единице обратно

  32. Андрей:

    А как быть с нечетными 1 и-1?

    1. Фото аватара Юрий:

      Так ведь программа правильно работает. 1 и -1 — нечетные числа.

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

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