07 апреля 2020

Арифметические операции

    Язык программирования, предоставляя возможность определения разнообразных типов данных, должен обеспечивать их обработку, т. к. его основной целью является реализация алгоритмов обработки данных. Выполнение допустимых действий над данными осуществляется с помощью набора определенных в языке программирования операций. Операция — это выполнение определенного действия над операндами, результатом которого является новое значение. С точки зрения математики операцию можно рассматривать как некую функцию, которая по заданным переменным (операндам) вычисляет новое значение. Все знают со школьной скамьи четыре основных арифметических действия, выполняемых над числами: сложение (+), вычитание (-), умножение (*) и деление (/). Эти действия (операции) мы всегда выполняем над двумя числами (операндами), получая в результате новое число. Язык программирования определяет не только арифметические операции над числовыми данными, но и операции, применимые к другим допустимым типам данных. Это могут быть операции над строками, массивами и т. д. Важно только одно, что есть операция, определяемая своим знаком, и есть участвующие в ней операнды, в совокупности позволяющие получить (вычислить) новое значение, которое может принадлежать к одному из допустимых типов. В качестве операндов можно использовать литералы, переменные и выражения, представляющие собой комбинации основных операций. Общий синтаксис операции можно представить следующим образом:
операнд знак_операции операнд
     Для некоторых операций один из операндов может быть опущен. В этом случае операция называется одноместной или унарной, например, вычисление противоположного по знаку значения операнда -$т. Если в операции участвуют два операнда, то операция называется двуместной или бинарной. Практически все допустимые операции являются унарными или бинарными, но в некоторых современных языках программирования определена од-на-единственная условная тернарная операция, требующая три операнда. Значением этой операции является второй или третий операнд, в зависимости от истинности и ложности первого:
операнд_1 ? операнд_2 : операнд_3

      Синтаксически выражение представляется в виде последовательности операндов и знаков операций, которая обычно интерпретируется слева направо учетом порядка старшинства операций, т. е. правил, определяющих, в какой последовательности выполняются присутствующие в выражении операции. Для изменения порядка выполнения используются круглые скобки. Результатом обработки интерпретатором выражения является некоторое вычисленное значение, которое используется в других конструкциях языка, реализующих алгоритм обработки данных.
     В этой главе подробно рассматриваются операции языка Perl и их использование при конструировании выражений. В языке Perl определено несколько десятков операций. Их можно сгруппировать по типу выполняемых действий (арифметические, побитовые, логические, отношения, присваивания), на какие данные они воздействуют (строковые, списковые, файловые), и не относящиеся ни к одному из перечисленных типов (операции запятая, ссылки, разыменования и выбора). Следуя именно такой классификации операций языка Perl, мы и познакомим с ними нашего читателя. Одни операции будут разобраны подробно, о других мы только дадим общее представление, отнеся более детальное описание в другие главы нашей книги.
     Все арифметические операции можно разбить на три группы: бинарные, унарные и увеличения/уменьшения. Их основное назначение — выполнить определенные вычисления над числовыми данными, но во всех арифметических операциях в качестве операндов могут выступать и строковые данные, причем не обязательно, чтобы они конвертировались в числовые данные.

Бинарные арифметические операции
     Бинарные арифметические операции — это известные всем четыре арифметических действия: сложение (+), вычитание (-), умножение (*) и деление (/), к которым добавляются еще два: остаток от деления двух целых чисел (%) и возведение в степень (**). Примененные к числовым данным или строковым, которые содержат .правильные литералы десятичных чисел, они выполняют соответствующие арифметические действия (пример 4.1).
3.14 + 123; # Результат: 126.14
"3.14" + "123"; # Результат: 126.14
"3.14" + 123; # Результат: 126.14
"3.14" * 10; # Результат: 31.4
300 - 200; # Результат: 100
300 / 200; # Результат: 1.5
3 % 2; # Результат: 1
2 ** 3; . # Результат: 8
(-2) ** 3; # Результат: -8 '
2 ** (-3); # Результат: 0.125
2.5 ** 1.5; # Результат: -23.95284707521047

      Как видим, бинарные арифметические операции "работают" именно так, как мы привыкли их использовать в обычных арифметических вычислениях в нашей повседневной жизни.

Замечание
Если операнд в операции получения остатка от деления целых чисел (%) является вещественным числом с дробной частью, то он преобразуется к целому простым отбрасыванием дробной части, после чего операция выполняется над целыми числами.
Замечание
Нельзя возводить отрицательное число не в целую степень. Если такое случается, то интерпретатор не выдает никакой ошибки, но результатом такой операции является нуль: (-2.5) ** (1.3) = о.
     В качестве операндов бинарных арифметических операций можно использовать строки, не содержащие правильные числовые литералы. В этом случае интерпретатор попытается выделить, начиная с первого символа, из содержимого строки число и использовать его в качестве соответствующего операнда заданной операции. Если не удается выделить правильный числовой литерал, то операнд принимает значение, равное о. Подобные ситуации демонстрируются в примере 4.2.
"3fl4" •+ "12-30"; # Результат: 15 ("3" + "12")
"а!20" + "12-30"; # Результат: 12 ("О" + "12")
."а!20" + "-0012-30"; # Результат: -12 ("О" + "-12")

Замечание
Если установить режим отображения предупреждающих сообщений интерпретатора (ключ -w), то при попытке использовать в бинарных арифметических операциях строки, не содержащей правильные числовые литералы, будет отображено сообщение вида:
Argument "al20" isn't numeric in add at D:\EXAMPLE1.PL line 2.

      Бинарные арифметические операции выполняются в скалярном контексте. Это означает, что операндами должны быть скалярные переменные, а переменные массивов скаляров и хеш-массивов принимают значения, равные, соответственно, количеству элементов массивов скаляров или количеству использованных в хеш-таблице записей в соответствии с требованиями скалярного контекста (пример 4.3).

@m = (2, 4, 6, 8, 10) ;
%ml = ( 1 => "а", 2 => "Ь"};
$n = 100;
$n + @m; # Результат: 105 (100 + 5)
@m + %ml; # Результат: 7 (5+2)

Замечание
В скалярном контексте хеш-массив принимает строковое значение, состоящее из числа использованных участков записей в хеш-таблице и числа выделенных участков записей, разделенных символом "/" (см. главу 3). Используемое в арифметических операциях число получается выделением из этой строки числового литерала, который как раз и соответствует количеству использованных в хеш-таблице записей.
Унарные арифметические операции
      В языке Perl есть только две унарные арифметические операции (+) и (-). Унарный плюс +, примененный к данным любого типа, представленным литералами или своими переменными, не имеет никакого семантического эффекта. Он полезен перед выражением в круглых скобках, стоящим непосредственно после имени функции, если необходимо чисто визуально акцентировать тот факт, что функция фактически является списковой операцией.
     Унарный минус (-) выполняет арифметическое отрицание числового операнда. Это означает, что если число было отрицательным, то оно станет положительным, и наоборот. Если операндом является идентификатор, то результатом выполнения этой операции будет строка, состоящая из символа "-", за которым следует идентификатор. Если операндом является строка, начинающаяся с символа минус или плюс, то результатом также будет строка, в которой минус заменен на плюс и наоборот. Для строк, не начинающихся с плюса или минуса, операция унарного минуса добавляет его первым символом в строку. Все перечисленные случаи употребления унарного минуса показаны в примере 4.4.

-'12.09'; # Результат: -12.09
-(-12.09);•# Результат: 12.09
-id; # Результат: '-id'
-'+id"; # Результат: '-id'
-"-id"; # Результат: "+id"
-'а!20'; # Результат: '-а!20'

Операции увеличения и уменьшения
     Операции увеличения (++) и уменьшения (--) аналогичны таким же операциям в языке С. (Авторы языка Perl не скрывают, что они многое заимствовали из этого языка.) Результат этих операций зависит от того, стоят ли они перед (префиксная форма) или после переменной (постфиксная форма). При использовании префиксной формы они, соответственно, увеличивают или уменьшают числовое значение переменной на единицу до возвращения значения. Постфиксная форма этих операций изменяет числовое значение переменной после возвращения ими значения. Действие этих операций на числовые переменные иллюстрируется примером 4.5 (операторы фрагмента программы выполняются последовательно).
$n = 10.7; # Начальное значение
$infl = —$n; # Результат: $infl = 9.7и$n=9.7
$inf2 = ++$n; # Результат: $inf2 = 10.7 и $n = 10.7
$postl = $n--; # Результат: $postl = 10.7 но $n= 9.7
$post2 = $n++; # Результат: $post2 = 9.7 но $n= 10.7

      Операция увеличения (префиксная и постфиксная), примененная к переменной, содержащей строку определенного вида, выполняется несколько необычно. Если строка состоит только из латинских букв, то возвращаемым значением операции увеличении будет строка, в которой последняя буква заменена на следующую по порядку букву алфавита, причем строчная заменяется строчной, а прописная прописной. Если строка завершается идущими подряд буквами "z" или "z", то все они заменяются соответственно на "а" или "А", а стоящая перед ними в строке буква заменяется на следующую букву алфавита. Если вся строка состоит из букв "z" и "z", то кроме замены этих букв в соответствии с предыдущим правилом, перед ними добавляется строчная или прописная буква "а" в зависимости от того, строчная или прописная буква "z" стояла первой в строке.

      Аналогичные действия осуществляются, если строка завершается последовательностью цифр: последняя цифра увеличивается на единицу. Если строка завершается идущими подряд цифрами 9, то все они заменяются на о, а примыкающий к ним символ "увеличивается" на единицу: для буквы он переходит в следующий по алфавиту, а для цифры в следующую по порядку цифру. Если последовательность целиком состоит из девяток, то все они заменяются на нули, перед которыми добавляется единица. Префиксная и постфиксная формы операции действуют как обычно. Несколько иллюстраций этих операций представлены в примере 4.6.

$s = "abc"
$sl = ++$s; # Результат: $sl = "abd"
$s = "abC";
$sl = ++$s; # Результат: $sl = "abD"
$s = "abz";
$sl = ++$s; # Результат: $sl = "аса"
$s = "abzZz";
$sl = ++$s; # Результат: $sl = "acaAa"
$s = "ab09";
$sl = ++$s; # Результат: $sl = "ablO"
$s = "99"; .
$sl = ++$s; # Результат: $sl = "100"

Замечание
Операция уменьшения (—) работает со специальными строками так же, как и с обычными. Осуществляется попытка выделить числовой литерал, начиная с первого символа. Если такое оказывается возможным, то числовое значение строки приравнивается выделенному числовому литералу, если нет — ее значение считается равным 0. После этого применяется операция уменьшения к вычисленному числовому значению строки.