Изменение значений переменных. Арифметические операции в Pascal
Создано: 29.03.2026
На прошлом уроке мы научились объявлять переменные, присваивать им значения, а также считывать и выводить значения переменных. Однако само слово "переменная" подсказывает, что переменная должна изменяться. На самом деле в Паскале и других языках со статической типизацией меняется не она сама, а хранимое в ней значение.
Самым очевидным способом изменить значение переменной является присваивание ей нового значения по ходу выполнения программы. Так здесь мы сначала присваиваем переменной a число 0.75, а потом 1:
var a: real; begin a := 0.75; writeln(a:4:2); // 0.75 a := 1; writeln(a:1:0); // 1 end.
С помощью комментариев показано, что будет выводиться на экран при выполнении процедуры writeln(). Обратите внимание, что хотя во втором случае мы присваиваем вроде бы целое число, но оно будет "воспринято" как вещественное без значащих цифр после запятой (в программировании вместо запятой используется точка).
На самом деле после знака присваивания может находиться не просто значение, а какие-либо операции. Переменной будет присвоен результат их выполнения. На этом уроке все наши операции будут арифметическими, то есть сложением, вычитанием, умножением или делением.
var a: real; begin a := -4.5 + 0.873; writeln(a:6:3); // -3.627 a := (1 - 0.62) * 2; writeln(a:6:3); // 0.760 a := 30 / 4; writeln(a:6:3); // 7.500 end.
Так выражение a := -4.5 + 0.873; выполняется в два этапа. Сначала происходит сложение и только после этого получившаяся сумма присваивается переменной.
Код выше несколько некорректен с точки зрения смысла. Если мы хотели бы сохранить результаты вычислений для последующего использования в программе, то следовало бы вводить три переменные, и каждой присваивать результат своего арифметического выражения. А так, помещая в участок памяти новое значение, мы затираем там старое. Тогда уж проще отказаться от переменной, то есть не хранить результат, а получать его и сразу выводить:
begin writeln(-4.5 + 0.873 :6:3); writeln((1 - 0.62) * 2 :6:3); writeln(30 / 4 :6:3); end.
Однако нередко в программах возникает необходимость не изменять значение переменной, а проделывать с ним те или иные операции без сохранения результата. Мы это уже видели в первом уроке, когда прибавляли к переменной a число 3. Немного усложним тот пример:
var a: integer; begin a := 10; writeln(a + 3 * 2); // 16 writeln(a / 2.5 :1:0); // 4 writeln(a); // 10 end.
Вспомним, что в таком выражении как, например, a + 3 * 2 из переменной считывается ее значение, и уже потом это значение, а не сама переменная, участвует в операциях.
Сама по себе здесь переменная a не меняется, так как нет никакой операции присваивания. Теперь рассмотрим такой вариант кода:
var a: integer; begin a := 10; a := a + 1; writeln(a); a := a + 1; writeln(a); end.
Если представить, что вместо оператора присваивания стоит равно, то с точки зрения математики выражение a := a + 1; выглядит ошибочным, так как переменная не может быть равна себе, измененной на какую-то величину. Но с точки зрения программирования это выражение не просто верное, оно очень даже естественное. Потому что в нем употребление имени переменной до знака присваивания и после него имеют совершенно разный смысл. Когда переменная участвует в арифметической операции, то используется ее значение. Когда же она находится перед оператором присваивания, то в нее записывается новое значение.
Спишите программу выше, скомпилируйте и выполните ее. Какие числа выводятся на экране? Как в процессе выполнения программы меняется значение переменной?
Конечно, мы можем делать и так, чтобы значение одной переменной вычислялось через значение другой:
var a, b: integer; begin a := 34; b := a + 22; writeln(a); // 34 writeln(b); // 56 a := 0; writeln(a); // 0 writeln(b); // 56 end.
Обратите внимание, что переменная b никак не связана с a. Просто на каком-то этапе для b было взято значение из a. Но если значение в a изменится, b об этом не узнает, потому что содержит в своем участке памяти не формулу a + 22, а уже готовое число 56.
Особое внимание в программировании уделяется операции деления, потому что часто в результате его выполнения получаются дробные числа. Многие языки программирования никак не оценивают результат, дробное там получилось число или целое. Вместо этого в них есть однозначное правило, что если производится операция обычного деления, то ее результат всегда будет вещественным числом. Поэтому даже если мы делим 4 на 2, все равно получим данное вещественного типа.
var a: integer; begin a := 4; writeln(a / 2); // 2.0000000000000000E+000 writeln(a / 2 :1:0); // 2 end.
Как следствие мы не можем целочисленной переменной присваивать результат обычного деления, так как Pascal не будет преобразовывать его к целому. Выражение ниже приведет к ошибке несовместимости типов, если переменная a объявлена как integer:
a := 4 / 2;
Однако в Паскале кроме обычного деления есть "необычное". Оператор этого деления обозначается не знаком слэша, а ключевым словом div. Необычность его в том, что оно в принципе целочисленное, так как вычисляется целое частное, а остаток отбрасывается. Так здесь в коде при делении 15-ти на 2 получается 7, а не 7.5:
var a, b: integer; c: real; begin a := 10 div 2; b := 15 div 2; writeln(a); // 5 writeln(b); // 7 c := 20 div 3; writeln(c); // 6.0000000000000000E+000 end.
Результат выполнения целочисленного деления можно присваивать вещественной переменной, потому что Pascal сам выполняет приведение целого типа к вещественному. В примере выше фактически мы присваиваем c значение 6, которое преобразуется в соответствующее вещественное. Как уже было сказано ранее, обратное неверно: нельзя целочисленной переменной присваивать вещественное число как есть. Pascal не может за вас решить, отбросить ли ему дробную часть или выполнить округление до целого.
Для присваивания целочисленной переменной дробного числа его надо явно преобразовать в целое с помощью функции trunc или round. Первая отбрасывает дробную часть, вторая округляет переданное в нее вещественное значение. Обе функции относятся к стандартным функциям языка Pascal. Такие встроены в язык и их достаточно много.
var a, b: integer; c: real; begin a := trunc(15 / 2); b := round(15 / 2); writeln(a); // 7 writeln(b); // 8 c := 4.25; a := round(c); writeln(a); // 4 writeln(trunc(255 * c)); // 1083 end.
Снова вернемся к целочисленному делению. Как-то нехорошо, что теряется остаток. Вполне возможно, что он может иметь важное значение в программе. Конечно он вычисляем, ведь если перемножить частное и делитель, а потом это произведение вычесть из исходного числа, то получится остаток:
var a, b, c: integer; begin a := 15; b := a div 2; c := a - b * 2; writeln('Целое частное: ', b); // 7 writeln('Остаток от деления: ', c); // 1 end.
Однако в языке Pascal есть оператор mod, который упрощает получение остатка. Если между делимым и делителем поставить mod вместо div, то будет получен остаток от деления, а не целое частное:
var a, b: integer; begin a := 15; b := a mod 2; // сохранили остаток a := a div 2; // изменили значение переменной writeln(a); // 7 writeln(b); // 1 end.
Что получится в результате выполнения следующих выражений: 15 div 2 mod 3 и 100 mod 65 div 7? Проверьте ваши предположения, написав программу, которая решает эти примеры.