На какие типы делятся арифметические операции
Арифметические операции производятся над числами. Значения, которые участвуют в операции, называются операндами. В языке программирования 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::cout1.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++ также сгенерирует предупреждение.
Переопределение порядка операций
На какие типы делятся арифметические операции
В C# используется большинство операций, которые применяются и в других языках программирования. Операции представляют определенные действия над операндами - участниками операции. В качестве операнда может выступать переменной или какое-либо значение (например, число). Операции бывают унарными (выполняются над одним операндом), бинарными - над двумя операндами и тернарными - выполняются над тремя операндами. Рассмотрим все виды операций.
Бинарные арифметические операции:
-
+ Операция сложения двух чисел:
int x = 10; int z = x + 12; // 22
int x = 10; int z = x - 6; // 4
int x = 10; int z = x * 5; // 50
int x = 10; int z = x / 5; // 2 double a = 10; double b = 3; double c = a / b; // 3.33333333
При делении стоит учитывать, что если оба операнда представляют целые числа, то результат также будет округляться до целого числа:
double z = 10 / 4; //результат равен 2
Несмотря на то, что результат операции в итоге помещается в переменную типа double, которая позволяет сохранить дробную часть, но в самой операции участвуют два литерала, которые по умолчанию рассматриваются как объекты int, то есть целые числа, и результат то же будет целочисленный. Для выхода из этой ситуации необходимо определять литералы или переменные, участвующие в операции, именно как типы double или float:
double z = 10.0 / 4.0; //результат равен 2.5
double x = 10.0; double z = x % 4.0; //результат равен 2
Также есть ряд унарных операций, в которых принимает участие один операнд:
-
++ Операция инкремента Инкремент бывает префиксным: ++x - сначала значение переменной x увеличивается на 1, а потом ее значение возвращается в качестве результата операции.
И также существует постфиксный инкремент: x++ - сначала значение переменной x возвращается в качестве результата операции, а затем к нему прибавляется 1.
int x1 = 5; int z1 = ++x1; // z1=6; x1=6 Console.WriteLine($" - "); int x2 = 5; int z2 = x2++; // z2=5; x2=6 Console.WriteLine($" - ");
int x1 = 5; int z1 = --x1; // z1=4; x1=4 Console.WriteLine($" - "); int x2 = 5; int z2 = x2--; // z2=5; x2=4 Console.WriteLine($" - ");
При выполнении сразу нескольких арифметических операций следует учитывать порядок их выполнения. Приоритет операций от наивысшего к низшему:
- Инкремент, декремент
- Умножение, деление, получение остатка
- Сложение, вычитание
Для изменения порядка следования операций применяются скобки.
Рассмотрим набор операций:
int a = 3; int b = 5; int c = 40; int d = c---b*a; // a=3 b=5 c=39 d=25 Console.WriteLine($"a= b= c= d=");
Здесь мы имеем дело с тремя операциями: декремент, вычитание и умножение. Сначала выполняется декремент переменной c, затем умножение b*a, и в конце вычитание. То есть фактически набор операций выглядел так:
int d = (c--)-(b*a);
Но с помощью скобок мы могли бы изменить порядок операций, например, следующим образом:
int a = 3; int b = 5; int c = 40; int d = (c-(--b))*a; // a=3 b=4 c=40 d=108 Console.WriteLine($"a= b= c= d=");
Ассоциативность операторов
Как выше было отмечено, операции умножения и деления имеют один и тот же приоритет, но какой тогда результат будет в выражении:
int x = 10 / 5 * 2;
Стоит нам трактовать это выражение как (10 / 5) * 2 или как 10 / (5 * 2) ? Ведь в зависимости от трактовки мы получим разные результаты.
Когда операции имеют один и тот же приоритет, порядок вычисления определяется ассоциативностью операторов. В зависимости от ассоциативности есть два типа операторов:
- Левоассоциативные операторы, которые выполняются слева направо
- Правоассоциативные операторы, которые выполняются справа налево
Все арифметические операторы являются левоассоциативными, то есть выполняются слева направо. Поэтому выражение 10 / 5 * 2 необходимо трактовать как (10 / 5) * 2 , то есть результатом будет 4.
Числовые типы, арифметические операции
На этом занятии мы поподробнее поговорим о представлении чисел и арифметических операциях над ними.
- int – для целочисленных значений;
- float – для вещественных;
- complex – для комплексных.
Основные арифметические операции
Пока такого понимания чисел будет вполне достаточно. Следующим шагом, нам с вами нужно научиться делать арифметические операции над ними. Что это за операции? Базовыми из них являются, следующие:
Оператор | Описание | Приоритет |
+ | сложение | 2 |
- | вычитание | 2 |
* | умножение | 3 |
/, // | деление | 3 |
% | остаток деления | 3 |
** | возведение в степень | 4 |
Давайте, я поясню их работу на конкретных примерах. Перейдем в консоль языка Python, чтобы выполнять команды в интерактивном режиме. Так будет удобнее для демонстрации возможностей вычислений. В самом простом варианте мы можем просто сложить два целых числа:
Получим результат 5. Но этот результат у нас нигде не сохраняется. Чтобы иметь возможность делать какие-либо действия с пятеркой, ее следует сохранить через переменную, например, вот так:
a = 2+3
Теперь a ссылается на объект с числом 5. Давайте разберемся, как работает эта строчка. Сначала в Python создаются два объекта со значениями 2 и 3. Оператор сложения берет эти значения, складывает их и формирует третий объект со значением 5. А, затем, через оператор присваивания, этот объект связывается с переменной a. В конце, если на объекты 2 и 3 не ссылаются никакие другие переменные, они автоматически удаляются из памяти сборщиком мусора. Возможно, вас удивило, что при такой простой операции сложения двух чисел выполняется столько шагов. Но в Python реализовано все именно так. И это справедливо для всех арифметических операций. Мало того, раз операция сложения возвращает объект с результатом, то можно сделать и такое сложение из трех чисел:
b = 2+3+4
И так далее, можно записать сколько угодно операций сложения в цепочку. Давайте теперь сложим целое число с вещественным:
c = 2 + 3.5
Очевидно, что результат получается тоже вещественным. Отсюда можно сделать вывод, что сложение целого числа с вещественным всегда дает вещественное значение. А вот при делении двух любых чисел, мы всегда будем получать вещественное число (даже если числа можно разделить нацело):
d1 = 8 / 2 d2 = 3 / 6
Если же нам нужно выполнить деление с округлением к наименьшему целому, то это делается через оператор:
d3 = 7 // 2
На выходе получаем значение 3, так как оно является наименьшим целым по отношению к 3,5. Обратите внимание, что при делении отрицательных чисел:
d3 = -7 // 2
получим уже значение -4, так как оно наименьшее по отношению к -3,5. Вот этот момент следует иметь в виду, применяя данный оператор деления. Следующий оператор умножения работает очевидным образом:
5 * 6 2 * 4.5
Обратите внимание, в последней операции получим вещественное значение 9.0, а не целое 9, так как при умножении целого на вещественное получается вещественное число. Давайте теперь предположим, что мы хотим вычислить целый остаток от деления. Что это вообще такое? Например, если делить 10 : 3 то остаток будет равен 1. Почему так? Все просто, число 3 трижды входит в число 10 и остается значение 10 - 3∙3 = 1. Для вычисления этого значения в Python используется оператор:
10 % 3
Если взять:
10 % 4
то получим 2. Я думаю, общий принцип понятен. Здесь есть только один нюанс, при использовании отрицательных чисел. Давайте рассмотрим четыре возможные ситуации:
9 % 5 # значение 4 -9 % 5 # значение 1 9 % -5 # значение -1 -9 % -5 # значение -4
Почему получаются такие значения? Первое, я думаю, понятно. Здесь 5 один раз входит в 9 и остается еще 4. При вычислении -9 % 5 по правилам математики следует взять наименьшее целое, делящееся на 5. Здесь – это значение -10. А, далее, как и прежде, вычисляем разность между наименьшим, кратным 5 и -9: -9 – (-10) = 1 При вычислении 9 % -5, когда делитель отрицательное число, следует выбирать наибольшее целое, кратное 5. Это значение 10. А, далее, также вычисляется разность: 9 – 10 = -1 В последнем варианте -9 % -5 следует снова выбирать наибольшее целое (так как делитель отрицателен), получаем -5, а затем, вычислить разность: -9 – (-5) = -4 Как видите, в целом, все просто, только нужно запомнить и знать эти правила. Кстати, они вам в дальнейшем пригодятся на курсе математики. Последняя арифметическая операция – это возведение в степень. Она работает просто:
2 ** 3 # возведение в куб 36 ** 0.5 # 36 в степени 1/2 (корень квадратный) 2 ** 3 ** 2 # 2^3^2 = 512
В последней строчке сначала 3 возводится в квадрат (получаем 9), а затем, 2 возводится в степень 9, получаем 512. То есть, оператор возведения в степень выполняется справа-налево. Тогда как все остальные арифметические операции – слева-направо.
Приоритеты арифметических операций
Давайте теперь посмотрим, что будет, если выполнить команду:
27 ** 1/3
Получим значение 9. Почему так произошло? Ведь кубический корень из 27 – это 3, а не 9? Все дело в приоритете арифметических операций (проще говоря, в последовательности их выполнения). Приоритет у оператора возведения в степень ** - наибольший. Поэтому здесь сначала 27 возводится в степень 1, а затем, 27 делится на 3. Получаем искомое значение 9. Если нам нужно изменить порядок вычисления, то есть, приоритеты, то следует использовать круглые скобки:
27 ** (1/3)
Теперь видим значение 3. То есть, по правилам математики, сначала производятся вычисления в круглых скобках, а затем, все остальное в порядке приоритетов. Приведу еще один пример, чтобы все было понятно:
2 + 3 * 5 # 17 (2 + 3) * 5 # 25
То есть, приоритеты работают так, как нас учили на школьных уроках математики. Я думаю, здесь все должно быть понятно. Также не забывайте, что все арифметические операторы выполняются слева-направо (кроме оператора возведения в степень), поэтому в строчке:
32 / 4 * 2
сначала будет выполнено деление на 4, а затем, результат умножается на 2.
Дополнительные арифметические операторы
В заключение этого занятия рассмотрим некоторые дополнения к арифметическим операторам. Предположим, что у нас имеются переменные:
i = 5 j = 3
И, далее, мы хотим переменную i увеличить на 1, а j – уменьшить на 2. Используя существующие знания, это можно сделать, следующим образом:
i = i + 1 j = j - 2 print(i, j)
Но можно проще, используя операторы:
i += 1 j -= 2
Результат будет прежним, но запись короче. Часто, в таких ситуациях на практике используют именно такие сокращенные операторы. То же самое можно делать и с умножением, делением:
i *= 3 j /= 4 print(i, j)
Арифметические операции: сложение, вычитание, умножение и деление
Все эти операции можно использовать как бинарные, то есть, слева и справа от них записываются выражения, над которыми выполняется соответствующая операция:
Здесь левые и правые операнды могут быть любыми выражениями, над которыми можно выполнять соответствующую арифметическую операцию. В самом простом случае – это переменные и числовые литералы.
Обратите внимание, все рассматриваемые арифметические операции являются именно операциями, а не операторами. Это значит, они вычисляют значение и возвращают его. Именно поэтому мы можем совершенно свободно присвоить вычисленный результат какой-либо переменной следующим образом:
int result = 10 + 5;
int result; result = 10 - 5;
Здесь точка с запятой в конце превращает арифметическую операцию в завершенный оператор. В частности, это означает, что арифметические операции можно продолжать, пока не встретится символ точка с запятой:
int result = 10 + 5 - 7 * 3;
Но обо всем по порядку. Давайте непосредственно в программе посмотрим на работу операций сложения, вычитания и умножения:
#include int main(void) { short a = -5; int b = 10; float c = 5.4f; double d = -6.5; int res_1 = a + b; short res_2 = 100 - b; float res_3 = 5.4 - c; double res_4 = d * 4; return 0; }
Вначале идет объявление четырех переменных разных типов с определенными начальными значениями. Затем, эти переменные используются в арифметических операциях наряду с числовыми литералами. Наверное, первое, что бросается в глаза, возможность использования смешанных типов данных при арифметических вычислениях. Да, язык Си нас в этом не ограничивает, в отличие от некоторых других языков высокого уровня, где смешение типов не допускается. Но возникает вопрос, как это в деталях работает? Начнем с первой операции сложения двух целочисленных переменных a и b. Они имеют разные типы: short и int. Так вот, компилятор языка Си целочисленные значения по умолчанию приводит к единому типу int и только потом выполняет их сложение. То есть, переменная a будет приведена к типу int и мы получаем сложение двух значений одного типа.
Я думаю, вы понимаете, почему переменная a приводится именно к типу int? Как мы с вами уже говорили, тип int может превышать по размеру тип short, то есть, он является более общим и наиболее употребительным для представления целых числовых значений. Когда меньший тип приводится к большему, такая операция называется повышением типа.
Конечно, в общем случае, типа int может быть недостаточно, например, когда используются очень большие числовые значения. В этом случае компилятор повышает тип до long или long long так, чтобы не происходило потери данных при их представлении.
В следующей строчке программы записана операция вычитания:
short res_2 = 100 - b;
Здесь все работает аналогичным образом. Литерал 100 по умолчанию представляется типом int, переменная b также имеет тип int и результат тоже сохраняется в памяти как число типа int. А далее, полученное значение типа int присваивается переменной res_2 типа short. Перед присваиванием также происходит приведение типов, в данном случае значение int к типу short, т.к. тип переменной res_2 компилятор поменять самовольно не может. В результате получаем операцию понижения типа, которая может привести к потере данных, если присваиваемое значение не укладывается в меньший по размеру тип short. Вот на это всегда следует обращать внимание, при реализации арифметических операций. Как только встречается понижение типа данных, потенциально возможна потеря данных.
В следующей строчке:
float res_3 = 5.4 - c;
мы тоже видим понижение типа от double к float. Как мы помним, числовой литерал вещественного числа представляется типом double. Переменная c также приводится к типу double и результат вычитания сохраняется на уровне этого типа данных. После этого, значение double присваивается переменной res_3 меньшего типа float. Снова имеем понижение типов и потенциальную возможность потери данных. Поэтому, чаще всего на практике вещественные числа описываются типом double, чтобы избежать подобных преобразований.
Наконец, последняя строчка:
double res_4 = d * 4;
Здесь вещественное число d типа double умножается на целочисленное значение 4. Строго говоря, компьютер не умеет выполнять арифметические операции с вещественными и целыми числами. В нем реализована арифметика либо над целыми, либо над вещественными числами, не смешивая их. Поэтому здесь число 4 сначала будет приведено к более общему типу double, и только потом выполнена операция умножения над вещественными числами.
И у нас остается еще одна операция деления. Я думаю, вы теперь легко поймете принцип ее работы. Запишем ее в нескольких вариациях:
#include int main(void) { short a = -5; int b = 10; float c = 5.4f; double d = -6.5; int res_1 = 7 / 2; /* 3 */ double res_2 = -9 / 2; /* -4 */ float res_3 = a / c; /* -0.9259. */ double res_4 = d / b; /* -0.65 */ return 0; }
Смотрите, когда происходит деление двух целочисленных значений, то результат также получается целочисленным. Причем, в соответствии со стандартом C99, дробная часть просто отбрасывается. Именно так образуются целые значения. То есть, здесь нет округления по правилам математики, а просто отбрасывание дробной части, какой бы она ни была. Это следует запомнить. Если же один из операндов является вещественным значением, то все числа приводятся к типу double и после этого выполняется операция деления. Поэтому переменные res_3 и res_4 принимают дробные значения.
Операция приведения типов
Вот такой нюанс есть у операции деления в языке Си и начинающие программисты здесь очень часто совершают ошибки, когда делят два целых числа, ожидая получить вещественное значение. В действительности же происходит обычное целочисленное деление. И здесь может возникнуть вопрос: а как нам разделить две целочисленные переменные, чтобы получилось вещественное число? То есть, ситуация выглядит следующим образом:
#include int main(void) { short a = -5; int b = 10; double res_1 = a / b; /* 0 */ return 0; }
Для этого необходимо одну, а лучше обе переменные привести к вещественному типу double, используя операцию приведения типов:
double res_1 = (double)a / (double)b; /* -0.5 */
То есть, перед выражением (в данном случае переменной) в круглых скобках указывается тип, к которому должны быть приведены данные. В нашем примере значения переменных a и b сначала приводятся к типу double, а затем, выполняется операция деления над вещественными числами. Как результат получаем вещественное значение -0,5.
Если же мы оперируем конкретными числовыми значениями, например:
double res_2 = 7 / 2;
то для получения вещественного значения их удобнее записать в виде вещественных чисел:
double res_2 = 7.0 / 2.0;
вместо того, чтобы приводить целые числа к вещественному типу.
Унарные операции - и +
Далее, операции + и - можно использовать не только как бинарные, но и как унарные, то есть, перед выражением ставить знаки минус и плюс следующим образом:
#include int main(void) { short a = -5; // -5 int b = -a; // 5 int d = -(7 + a); // -(7 + -5) = -2 return 0; }
В первом случае знак минус стоит перед числовым литералом 5 и определяет его как отрицательное число, которое, затем, присваивается переменной a. В следующей строчке минус указан перед переменной и инвертирует знак числового значения, которое присваивается переменной b. При этом значение в переменной a не меняется. Наконец, в третьей строчке унарный минус поставлен перед выражением (7 + a). Соответственно, сначала вычисляется операция внутри скобок, а затем, выполняется инвертирование знака.
По аналогии можно использовать и унарный плюс, хотя, на практике он почти никогда не используется, т.к. по умолчанию значения определяются как положительные и лишний раз подчеркивать этот факт не имеет особого смысла.
Приоритеты арифметических операций
Важно знать, что приоритет любой унарной операции в языке Си выше, чем бинарной. Например, в следующей строчке:
int res = -10 + 7;
сначала будет выполнен унарный минус и только после этого бинарная операция сложения. Или так:
int res = -10 * 7;
Здесь также сначала унарный минус будет применен к числу 10 и только после этого выполнится бинарная операция умножения.
Если рассматривать бинарные арифметические операции, то сначала выполняются умножение и деление, а затем, сложение и вычитание. То есть, приоритет операций умножения и деления выше, чем у сложения и вычитания. Здесь все ровно так, как нас учат в школе на уроках математики. Например:
short a = -5, b = 7, c = 4; double D = b * b - 4 * a * c;
Сначала вычисляются умножения, а затем, бинарная операция вычитания. Причем, обратите внимание, порядок вычисления первого умножения b * b и второго 4 * a * c стандартом языка Си не определен. Разработчики компиляторов могут делать это в произвольном порядке с целью повышения скорости работы программы. Поэтому нет гарантии, что сначала вычислится b * b и только потом 4 * a * c. Порядок может быть другим. Это очень важный момент. А вот порядок вычисления подряд идущих арифметических операций с одинаковым приоритетом всегда выполняется слева-направо. То есть в выражении 4 * a * c сначала будет выполнено первое умножение и только потом – второе. В этом мы можем быть уверены. Поэтому запись вида:
double res = 5 / 3 * 2;
означает, что сначала 5 делится на 3 и результат умножается на 2. Это эквивалентно выражению (5 * 2) / 3. Иногда путаются и считают, что оно соответствует выражению 5 / (3 * 2). Но это неверно из-за строго порядка вычислений слева-направо.
Если нужно изменить порядок вычислений, то есть, приоритеты, то для этого используются круглые скобки, например, следующим образом:
int perimetr = 2 * (b + c);
Сначала будет вычислено выражение внутри скобок и только потом умножение на два.
В заключение этого занятия приведу простой пример программы, которая запрашивает два числа и на их основе вычисляет площадь треугольника:
#include int main(void) { double height, a; printf("Enter the height and length of the triangle's base: "); int res = scanf("%lf %lf", &height, &a); if(res != 2) { // проверка, что res не равна двум printf("Data entry error\n"); return 0; // завершение функции main и программы } double sq = height * a / 2.0; printf("The square of the triangle is: %.2f", sq); return 0; }
Вначале с помощью функции scanf() осуществляется ввод высоты и основания треугольника, затем, проверка, что данные были прочитаны корректно. Для этого, забегая вперед, я воспользовался условным оператором if, в котором проверяю, что переменная res не равна двум. Если это так, значит, произошла ошибка ввода значений. В этом случае выводится сообщение об ошибке в консоль и программа завершается. Если же данные введены верно, то вычисляется площадь треугольника и это значение выводится в консоль. Как видите, все достаточно просто.
На следующем занятии мы продолжим эту тему и рассмотрим следующую (заключительную) группу арифметических операций, а также особенности их работы.
Видео по теме
Язык Си. Рождение легенды
#1. Этапы трансляции программы в машинный код. Стандарты
#2. Установка компилятора gcc и Visual Studio Code на ОС Windows
#3. Структура и понимание работы программы "Hello, World!"
#4. Двоичная, шестнадцатеричная и восьмеричная системы счисления
#5. Переменные и их базовые типы. Модификаторы unsigned и signed
#6. Операция присваивания. Числовые и символьные литералы. Операция sizeof
#7. Стандартные потоки ввода/вывода. Функции putchar() и getchar()
#8. Функция printf() для форматированного вывода
#9. Функция scanf() для форматированного ввода
#10. Арифметические операции: сложение, вычитание, умножение и деление
#11. Арифметические операции деления по модулю, инкремента и декремента
#12. Арифметические операции +=, -=, *=, /=, %=
#13. Булевый тип. Операции сравнения. Логические И, ИЛИ, НЕ
#14. Условный оператор if. Конструкция if-else
#15. Условное тернарное выражение
#16. Оператор switch множественного выбора. Ключевое слово break
#17. Битовые операции И, ИЛИ, НЕ, XOR. Сдвиговые операции
#18. Генерация псевдослучайных чисел. Функции математической библиотеки
#19. Директивы макропроцессора #define и #undef
#20. Директива #define для определения макросов-функций. Операции # и ##
#21. Директивы #include и условной компиляции
#22. Оператор цикла while
#23. Оператор цикла for
#24. Цикл do-while с постусловием. Вложенные циклы
#25. Операторы break, continue и goto
#26. Указатели. Проще простого
#27. Указатели. Приведение типов. Константа NULL
#28. Долгожданная адресная арифметика
#29. Введение в массивы
#30. Вычисление размера массива. Инициализация массивов
#31. Указатели на массивы
#32. Ключевое слово const с указателями и переменными
#33. Операции с массивами копирование, вставка, удаление и сортировка
#34. Двумерные и многомерные массивы. Указатели на двумерные массивы
#35. Строки. Способы объявления, escape-последовательности
#36. Ввод/вывод строк в стандартные потоки
#37. Строковые функции strlen(), strcpy(), strncpy(), strcat(), strncat()
#38. Строковые функции сравнения, поиска символов и фрагментов
#39. Строковые функции sprintf(), atoi(), atol(), atoll() и atof()
#40. Объявление и вызов функций
#41. Оператор return. Вызов функций в аргументах
#42. Прототипы функций
#43. Указатели как параметры. Передача массивов в функции
#44. Указатели на функцию. Функция как параметр (callback)
#45. Стековый фрейм. Автоматические переменные
#46. Рекурсивные функции
#47. Функции с произвольным числом параметров
#48. Локальные и глобальные переменные
#49. Локальные во вложенных блоках
#50. Ключевые слова static и extern
#51. Функции malloc(), free(), calloc(), realloc(), memcpy() и memmove()
#52. Перечисления (enum). Директива typedef
#53. Структуры. Вложенные структуры
#54. Указатели на структуры. Передача структур в функции
#55. Реализация стека (пример использования структур)
#56. Объединения (union). Битовые поля
#57. Файловые функции: fopen(), fclose(), fgetc(), fputc()
#58. Функции perror(), fseek() и ftell()
#59. Функции fputs(), fgets() и fprintf(), fscanf()
#60. Функции feof(), fflush(), setvbuf()
#61. Бинарный режим доступа. Функции fwrite() и fread()
© 2023 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта