Название | Длина, байт | Кол-во значащих цифр | Диапазон десятичного порядка |
Real | 6 | 11...12 | -39...+38 |
Single | 4 | 7...8 | -45…+38 |
Double | 8 | 15...16 | -324...+308 |
Extended | 10 | 19...20 | -4932...+4932 |
Comp | 8 | 19...20 | -9.2*10+18…9.2*1018 (-263…(263-1)) (диапазон значений) |
Вещественное число в ТР может занимать от 4 до 10 смежных байт и имеет следующую структуру в памяти компьютера:
s | е | m |
Здесь s – знаковый разряд числа (один двоичный разряд), е – экспоненциальная часть (содержит порядок в двоичном представлении), m – мантисса числа (в двоичном представлении). Мантисса имеет длину от 23 (для Single) до 63 (для Extended) двоичных разрядов, что обеспечивает ту точность в десятичных цифрах, которая обозначена в таблице.
Вещественные значения могут записываться обычным способом с десятичной точкой (Х := -0.009), а также в экспоненциальном формате (Y := 123.4e-23). Если присутствует десятичная точка, за ней и перед ней д.б. хотя бы одна цифра. Если есть символ е - за ним д.б. хотя одна цифра.
Несмотря на большое разнообразие вещественных типов, все они кроме Real вводятся в расчете на арифметический сопроцессор – устройство, которое подключается непосредственно к центральному процессору и предназначен для выполнения операций над числами в формате с плавающей точкой и длинными целыми числами. Сопроцессор значительно (в десятки раз) ускоряет вычисления, связанные с вещественными числами. В процессорах, начиная с 80486 он встроен. Сопроцессор всегда обрабатывает числа в формате Extended (наиболее мощном). При этом остальные вещественные типы получаются простым усечением результатов до нужных размеров, что применяется в основном для экономии памяти. Т.е. если
Var
e1,e2 : Extended;
e3 : Double;
result : Single;
. . .
result := e1*e2/e3;
то значение выражения справа будет вычислено как тип Extended. Но при присваивании его переменной result меньшей мощности Single будет произведено усечение и значительно уменьшится число значащих цифр после десятичной точки.
Тип Real оптимизирован на работу без сопроцессора, поэтому его использование при наличии сопроцессора будет крайне неэффективно (время, «съедаемое» на преобразование его в сопроцессорный тип, перекрывает ускорение, а точности при этом не добавляется). Поэтому, если предполагается использовать разработанную программу на разных компьютерах (с сопроцессором и без него), целесообразно ввести свой вещественный тип (например, Float), и с помощью него описать все переменные. Конкретный тип, которому соответствует Float, зависит от наличия сопроцессора.
Type
Float = Real; {без сопроцессора}
Float = Double; {с сопроцессором}
Var
X : Float;
Y : array [1..9] of Float;
Чтобы программа могла задействовать возможности сопроцессора она должна иметь в своем начале директиву (ключ компилятора) $N+. Однако даже если в компьютере нет сопроцессора, ТР дает возможность эмулировать его работу программным путем. Т.е. можно создать программу, которая будет работать с вещественными числами большой точности, независимо от наличия сопроцессора. Это достигается существенными потерями в скорости счета. Включением эмуляции управляет ключ компилятора $E.
Особое место занимает тип Comp. Он трактуется как вещественное число без экспоненциальной и дробной части. Фактически, Comp – это «большое» целое число со знаком, сохраняющее 19…20 значащих цифр. В то же время тип Comp полностью совместим с любыми другими вещественными типами, над ним определены все вещественные операции и т.д. Наиболее подходящей областью применения являются бухгалтерские операции, когда денежные суммы выражаются в целых рублях (копейках), а действия над ними могут привести к очень длинным целым числам.
В ТР имеется набор стандартных процедур и функций, которые работают с вещественными и целыми данными.
МАТЕМАТИЧЕСКИЕ ФУНКЦИИ
ABS(X) – возвращает абсолютное значение аргумента Х (Х – целое/вещественное, результат – как у аргумента);
Pi – значение числа «Пи» (результат – вещественный); точность зависит от наличия сопроцессора (соответственно, 10 либо 14 знаков после запятой); может использоваться в вычислениях как константа, но не может быть подставлена в вычисляемые константы раздела Const;
SQR(X) – возвращает квадрата Х (Х – целое/вещественное, результат – как у аргумента);
SIN(X), COS(X), ArcTan(X) – возвращают значения синуса, косинуса и арктангенса (угол в радианах) (Х – целое/вещественное, результат – вещественное); ArcTan возвращает главное значение в диапазоне от –Pi/2 до Pi/2.
SQRТ(X) – возвращает квадратный корень из Х (Х > 0 – целое/вещественное, результат – вещественное);
EXP(X), LN(X) – возвращает экспоненту или натуральный логарифм Х (Х – целое/вещественное, результат – вещественное);
FRAC(X) – дробная часть числа Х (Х – целое/вещественное, результат – вещественное);
INT(X), TRUNC(X) – целая часть числа Х (Х – целое/вещественное, результат – у int – вещественный (т.е. после точки нули), - у trunc – целый:LongInt) {такая двойственность бывает полезна в операторах присваивания};
ROUND(X) – округление Х до ближайшего целого (Х – целое/вещественное, результат – целое:LongInt);
RANDOM(X) – возвращает случайное целое число из диапазона от 0 до Х (X и результат – Word);
RANDOM – возвращает случайное число от 0 до 1 (результат – вещественный);
ODD(X) – возвращает True, если Х – нечетное число, и False, если Х - нечетное (Х – целое, результат – логический)
МАТЕМАТИЧЕСКИЕ ПРОЦЕДУРЫ
RANDOMIZE – процедура гарантирует несовпадение последовательностей случайных чисел, выдаваемых функцией Random.
INC(var X : целое), DEC(var X : целое) – увеличивает или уменьшает значение Х на 1;
INC(var X : целое; N : целое), DEC(var X : целое; N : целое) – увеличивает или уменьшает значение Х на N;
Пример,
X := 2;
INC(X,4);
дает в результате Х = 6.
CТРУКТУРИРОВАННЫЕ ТИПЫ
Любой из структурированных (агрегативных) типов характеризуется множественностью образующих этот тип элементов, т.е. переменная или константа такого типа всегда имеет несколько компонентов. Каждый компонент может в свою очередь принадлежать структурированному типу, что позволяет говорить о возможной вложенности типов. В ТР допускается произвольная глубина вложенности типов, однако, суммарная глубина любого из них во внутреннем представлении не должна превышать 65520 байт.
МАССИВЫ
Особенность массивов в том, что все их компоненты являются данными одного типа (который тоже может быть структурированным). Компоненты массива легко упорядочиваются, обеспечить доступ к любому компоненту можно простым указанием его порядкового номера. Описание массива задается следующим образом:
<имя типа> = array [ <список инд. типов> ] of <тип>
<список инд. типов> – список из одного или нескольких индексных типов, разделенных запятыми, весь список заключен в квадратные скобки. В качестве индесксных типов можно использовать любые порядковые типы, кроме LongInt и типов диапазонов с базовым типом LongInt. Например,
Type
Vector = array [1..3] of Real; {инд. тип – тип-диапазон}
Var
R,V : Vector;
Определить переменную как массив можно и без предварительного описания типа массива, т.е.
Var
R,V : array [1..3] of Real;
В большинстве случаев в качестве индексного типа используется тип-диапазон (как в примере), в котором задаются границы изменения индексов.
Т.к. тип элементов массива (за словом of) – это любой тип ТР, то он может быть в частности, и другим массивом.
Type
Matrix = array [0..5] of array [-2..2] of array [Сhar] of Real;
Такой 3-х мерный массив может быть записан более компактно
Type
Matrix = array [0..5,-2..2,Сhar] of Real;
Доступ к элементу массива осуществляется через запись индекса в квадратных скобках после записи имени массива. Т.е.
Var
m: Matrix;
Begin
…
m[1,0,’d’] := 5; {обе записи - допустимы}
m[1][0][‘n’] := 6;
End.
В ТР можно одним оператором присваивания передать все элементы одного массива другому массиву того же типа.
Var
a,b : array [1..5] of Real;
Begin
…
a := b;
End.
После этого присваивания все элементы массива а получат значения соответствующих элементов массива b.
Операции отношения к массивам не применимы. Т.е. оператор
if a = b then …
неверен. Следовательно, сравнивать массивы можно лишь поэлементно.
ТР имеет специальный режим компиляции, относящийся к массивам и задаваемый ключом {$R}. Если вся программа или ее фрагмент компилировался в режиме {$R+}, то при обращении к элементам массива будет проверяться принадлежность значения индекса объявленному диапазону, и в случае нарушения границ будет выдано сообщение об ошибке (201 – Range check Error). В режиме {$R-} никаких проверок не производится и некорректное значение индекса извлечет из памяти некое значение, не относящееся к данному массиву. Обычно отлаживают программу в режиме $R+, а эксплуатируют – в режиме $R- для уменьшения исполняемого exe-файла и времени его выполнения.
ЗАПИСИ
Запись – это структура данных, состоящая из фиксированного числа компонентов, которые называются полями записи. В отличие от массива, компонетны (поля) записи могут быть различного типа. Поля имеют свои имена. Тип «запись» задается следующим образом:
<имя типа> = record <список полей> end
<список полей> - последовательность разделов записи, между которым ставится точка с запятой. Каждый раздел состоит из одного или нескольких имен полей, отделяемых друг от друга запятыми. Следом на именами ставится двоеточие и описание типа поля (полей). Например,
Type
Data = record
X,Y : integer;
Z : char
end;
Var
D1,D2 : Data;
Begin
…
D1.X := 10;
D2.Z := ‘n’;