Арифметические выражения
С помощью арифметических выражений выполняются все основные вычисления в программах. В состав арифметического выражения могут входить константы, переменные, функции, знаки арифметических операций и круглые скобки. Правила составления выражений, при некоторых ограничениях, специфических для программирования (отсутствие альтернативных форм записи операции умножения и деления, запрещение опускать знак операции умножения, ограничения на перечень выполняемых операций и т. д.), позволяют максимально приблизить их к обычным алгебраическим формулам, используемым в математике. В выражениях используются также некоторые специфические знаки операций. Выражения вычисляются слева направо с учетом приоритета операций. Для изменения приоритета операций используются круглые скобки. Выражения могут составляться из констант, переменных разных типов и функций. Основные арифметические операции обозначаются с помощью следующих знаков: * умножение / деление % вычисление остатка при делении целых чисел. + сложение — вычитание (операции возведения в степень в языке C++ нет). Из этих операций более высоким приоритетом обладают операции умножения, деления и вычисление остатка, а сложение и вычитание
22 имеют меньший приоритет. Между собой операции умножения и деления так же, как и операции сложения и вычитания, имеют одинаковый приоритет. Примеры оформления выражений: 2 * x + 0.2 a / (x + y) (a + 2) * (b — 0.5) sin(x — РI / 2) * cos(y) Если в выражении записана функция, то ее приоритет наивысший. Операция % позволяет вычислить остаток от деления двух целых чисел. Например, в результате выполнения операции 17 % 5 будет получено число 2 . Операция % имеет такой же приоритет, как и операции умножения и деления; эта операция не выполняется для чисел с плавающей точкой (хотя в принципе она имеет смысл, так как остаток можно вычислять не только в целых числах, но и в десятых, сотых долях и т.д.). Но этот же результат можно получить при предварительном умножении исходных чисел с плавающей точкой на соответствующую степень десятки с последующим преобразованием чисел в целые. Полученный затем остаток при выполнении операции % будет представлять остаток в десятых, сотых и т. д. в зависимости от выбранной степени десятки. Особенностью выполнения операции деления для целых чисел является отбрасывание дробной части. Например, если 1 разделить на 2 , то результат будет 0 . Для получения правильного результата требуется один из операндов преобразовать к типу числа с плавающей точкой. Если 1.0 (это число с плавающей точкой) разделить на 2 (или 1 разделить на 2.0 ), то в результате будет 0.5 . Другие способы описаны в параграфе «Преобразование типов».
Операция присваивания
Формально операция присваивания имеет вид математического равенства a = b , где » a » — имя переменной, а » b» — арифметическое выражение. Фактически операция присваивания засылает численное
23 значение результата, полученное при вычислении арифметического выражения, в ячейку памяти, выделенную для хранения переменной, имя которой записано слева от знака равенства. По этой причине действительными являются операции вида k = k + 2 . Действительно, на арифметическое выражение не налагается ограничение, чтобы оно не содержало переменной, записанной слева от знака равенства. Это происходит потому, что сначала вычисляется выражение, а затем выполняется засылка результата в ячейку памяти, обозначенную именем переменной. Допустим, что k в предыдущем примере имеет значение 5 , тогда сначала вычисляется 5 + 2 = 7 , а затем этот результат засылается в ячейку, обозначенную именем k , т.е. k получит значение 7 . В математике такие равенства не имеют смысла, поскольку они и обозначают действительные равенства, тогда как в программировании они обозначают последовательность выполнения сначала вычислений, а затем пересылки информации. Когда имя, записанное слева от знака равенства, не совпадает с именами, имеющимися в выражении справа от знака равенства, тогда оператор присваивания совпадает и по смыслу с математическим равенством. Этот факт можно выразить и другими словами: знак равенства обозначает пересылку справа налево (но не наоборот) с одновременным выполнением необходимых для этого действий. Но за одну операцию может пересылаться только одно данное. Поэтому, если справа от знака равенства записано выражение, то оно вычисляется, чтобы преобразовать его в одно число. По этой же причине слева от знака равенства не может быть записано число или выражение, хотя такая форма записи в математике применяется. Если тип данных для вычисленного арифметического выражения не совпадает с типом переменной, записанной слева от знака равенства, то автоматически выполняется преобразование к типу этой переменной. В языке С++ знак равенства обозначает операцию присваивания, а не оператор присваивания, как это имеет место в других языках
24 программирования. Операция от оператора отличается тем, что операция может применяться в арифметических выражениях, а оператор нет. Благодаря этому в языке C++ возможны такие записи: a = b = c = d = 0; (присвоение нескольким переменным одного и того же значения). x = 2 * (a = 3 + b); (выполнение присваивания в арифметическом выражении). Другими словами, знак равенства может означать как операцию присваивания (в последнем примере a = 3 + b ), так и оператор присваивания значения вычисленного выражения x = 2 * (a = 3 + d);. В языке C++ используются некоторые специфические формы записи операции присваивания. К таким операциям относятся ++ увеличение на единицу (инкремент) и — уменьшение на единицу (декремент). Фактически они обозначают соответственно прибавление к переменной 1 или вычитание из переменной 1 с соответствующим изменением переменной. x++; можно записать как x = x + 1; Операция x—; означает x = x — 1; Операции ++ и — записываются либо перед именем переменной, либо после него. В первом случае сначала выполняется приращение, а затем полученное значение используется в выражении. Во втором случае приращение выполняется после использования значения переменной. Это правило применяется, когда операции записаны в арифметическом выражении. В любом случае, когда выпол-
25 нение программы достигает точки с запятой в операторе, содержащем операцию приращения (или уменьшения), эта операция оказывается выполненной, независимо от места записи знаков ++ или —. Таким образом, записи x++; и ++x; являются равноценными и приводят к одному и тому же результату. Пусть теперь имеется оператор: z = x * y++; Если перед выполнением этого оператора x имеет значение 4 , а y равен 5 , то после выполнения вычислений z получит значение 20 , т.е. выражение было вычислено при начальном значении y , но после выполнения оператора y будет иметь значение 6 . Но при выполнении оператора: z = x * ++y; сначала будет увеличено значение y , и только затем вычислено значение z, т.е. z получит значение 24 . Операции ++ и — можно рассматривать как редуцированные формы записи операторов присваивания, но выражение x * y++; можно записать только с помощью двух операторов присваивания: y = x * y; y = y + 1; Для широко распространенных в программировании операторов вида: n = n + b; n = n * b; и т. д., где n является именем переменной, а b — выражением. В языке C++ может использоваться сокращенная запись оператора присваивания:
26 | |
Оператор присваивания | Форма записи в языке С++: |
n = n + b | n += b |
n = n — b | n -= b |
n = n * b | n *= b |
n = n / b | n /= b |
n = n + b | n += b |
Например, оператор | |
x = x / (k + 1); | |
можно записать как | |
x /= k + 1; |
Более наглядна была бы запись знака операции после знака равенства, но тогда запись вида n =- b; трактовалась бы как изменение знака b , поэтому и принята указанная форма записи. Отметим, что знаки операций при сокращенной записи оператора присваивания нельзя разделять пробелом. Они всегда записываются слитно ( += , но не + =). В выражениях и в операторах присваивания могут использоваться константы и переменные разных типов. Преобразование результатов вычисления выражений к конкретному типу данных выполняется автоматически. При этом окончательный тип данного преобразуется к типу данного, входящего в выражение, который позволяет представить результат при наибольшем диапазоне значений. Например, результат вычисления выражения, содержащего величины типа int и double , будет типа double . В выражениях при вычислениях могут использоваться также величины типа char . Если в операторе присваивания, в котором используются разнотипные целочисленные переменные, тип переменной, которой присваивается значение, не совпадает с окончательным типом данного для вычисленного выражения, тип вычисленного выражения преоб-
2.5. Арифметические выражения
Арифметические выражения строятся из операндов, арифметических операций и круглых скобок. Операндами могут быть константы, переменные и функции.
В бесскобочных арифметических выражениях операции выполняются слева направо в соответствии с их приоритетом.
1. * (умножение); / (деление); % ( остаток от деления целых чисел).
Изменить порядок выполнения операций можно с помощью круглых скобок. Выражение, заключенное в круглые скобки, выполняется в первую очередь. Например, выражению: а/b*с соответствует математическая запись: , а выражению а/(b*с) – запись .
Тип арифметического выражения определяется типом входящих и него операндов.
Арифметическое выражение является целым, если все входящие и него операнды целого типа.
Если в арифметическом выражении содержится хотя бы один вещественный операнд, то результат — вещественный. Целые операнды в вещественном арифметическом выражении всегда преобразуются к вещественному типу.
Операция выделения остатка или деление по модулю ( % ) применима только к целым числам. Результат ее выполнения имеет целый тип.
Исключение составляет операция деления с использованием символа ‘/’ (косая черта). Результат выполнения этой операции всегда зависит от типа операндов.
Например, значением выражения 2/5 будет число 0.