К порядковым типам относятся (см. рис.4.1) целые, логический, символьный, перечисляемый и тип-диапазон. К любому из них применима функция ORD(X), которая возвращает порядковый номер значения выражения X. Для целых типов функция ORD(X) возвращает само значение X, т.е. ORD(X) = X для X, принадлежащего любому шелому типу. Применение ORD(X) к логическому, символьному и перечисляемому типам дает положительное целое число в диапазоне от 0 до 1 (логический тип), от 0 до 155 (символьный), от 0 до 65535 (перечисляемый). Тип-диапазон сохраняет все свойства базового порядкового типа, поэтому результат применения к нему функции ORD(X) зависит от свойств этого типа.
К порядковым типам можно также применять функции:
PRED (X) — возвращает предыдущее значение порядкового типа (значение, которое соответствует порядковому номеру ORD(X)- 1), т.е.
ORD(PRED(X)) = ORD(X) — 1;
SUCC (X) — возвращает следующее значение порядкового типа, которое соответствует порядковому номеру ORD(X) +1, т.е.
ORD(SUCC(X)) = ORD(X) + 1.
Например, если в программе определена переменная
var
с : Char;
begin
с := ‘5’ ;
end.
то функция PRED(C) вернет значение ‘4’, а функция SUCC(C) — значение ‘6’.
Если представить себе любой порядковый тип как упорядоченное множество значий, возрастающих слева направо и занимающих на числовой оси некоторый отрезок, то функция PRED(X) не определена для левого, a SUCC(X) — для правого конца этого отрезка.
Целые типы. Диапазон возможных значений целых типов зависит от их внутреннего представления, которое может занимать один, два или четыре байта. В табл. 4.1 приводится название целых типов, длина их внутреннего представления в байтах и диапазон возможных значений.
Таблица 4.1
Целые типы | ||
Название | Длина, байт | Диапазон значений |
Byte | 0. . .255 | |
ShortInt | -128. . .+127 | |
Word | 0. . .65535 | |
Integer | -32768.. .+32767 | |
LongInt | -2 147 483 648… +2 147 483 647 |
При использовании процедур и функций с целочисленными параметрами следует руководствоваться «вложенностью» типов, т.е. везде, где может использоваться WORD, допускается использование BYTE (но не наоборот), в LONGINT «входит» INTEGER, который, в свою очередь, включает в себя SHORTINT.
Перечень процедур и функций, применимых к целочисленным типам, приведен в табл.4.2. Буквами b, s, w, i, l обозначены выражения соответственно типа BYTE, SHORTINT, WORD, INTEGER и LONGINT, x — выражение любого из этих типов; буквы vb, vs, vw, vi, vl, vx обозначают переменные соответствующих типов. В квадратных скобках указывается необязательный параметр.
Таблица 4.2
Стандартные процедуры и функции, применимые к целым типам | ||
Обращение | Тип результата | Действие |
abs (x) | x | Возвращает модуль х |
chr(b) | Char | Возвращает символ по его коду |
dec (vx[, i] ) | — | Уменьшает значение vx на i, а при отсутствии i -на 1 |
inc(vx[, i] ) | — | Увеличивает значение vx на i, а при отсутствии i — на 1 |
Hi(i) | Byte | Возвращает старший байт аргумента |
Hi(w) | To же | То же |
Lo(i) | Возвращает младший байт аргумента | |
Lo (w) | То же | |
odd(l) | Boolean | Возвращает True, если аргумент — нечетное число |
Random (w) | Как у параметра | Возвращает псевдослучайное число, равномерно распределенное в диапазоне 0…(w-l) |
sgr (x) | X | Возвращает квадрат аргумента |
swap ( i ) | Integer | Меняет местами байты в слове |
swap (w) | Word |
При действиях с целыми числами тип результата будет соответствовать типу операндов, а если операнды относятся к различным целым типам, — типу того операнда, который имеет максимальную мощность (максимальный диапазон значений). Возможное переполнение результата никак не контролируется, что может привести к недоразумениям, например:
var
а : Integer;
х, у : Real;
begin
а := 32767; {Максимально возможное значение типа INTEGER}
х := а + 2; {Переполнение при вычислении этого выражения!}
у := LongInt(а)+2; {Переполнения нет после приведения переменной к более мощному типу}
WriteLn(x:10:0, у:10:0)
end.
В результате прогона программы получим
-32767 32769
Логический тип. Значениями логического типа может быть одна из предварительно объявленных констант FALSE (ложь) или TRUE (истина). Для них справедливы правила:
ord(False) = 0;
ord(True) = 1;
FalseTrue;
succ(False)= True;
pred(True) = False.
Поскольку логический тип относится к порядковым типам, его можно использовать в операторе счетного типа, например:
var
1 : Boolean;
begin
for 1 := False to True do ….
Символьный тип. Значением символьного типа является множество всех символов ПК. Каждому символу приписывается целое число в диапазоне 0…255. Это число служит кодом внутреннего представления символа, его возвращает функция ORD.
Для кодировки используется код ASCII (American Standard Code for Information Interchange — американский стандартный код для обмена информацией). Это 7-битный код, т.е. с его помощью можно закодировать лишь 128 символов в диапазоне от 0 до 127. В то же время в 8-битном байте, отведенном для хранения символа в Турбо Паскале, можно закодировать в два раза больше символов в диапазоне от 0 до 255. Первая половина символов ПК с кодами 0…127 соответствует стандарту ASCII (табл. 4.3). Вторая половина символов с кодами 128…255 не ограничена жесткими рамками стандарта и может меняться на ПК разных типов (в прил.2 приведены некоторые распространенные варианты кодировки этих символов).
Таблица 4.3
Кодировка символов в соответствии со стандартом ASCII | |||||||
Код | Символ | Код | Символ | Код | Символ | Код | Символ |
NUL | BL | ® | ‘ | ||||
ЗОН | ! | A | a | ||||
STX | В | b | |||||
ЕТХ | # | С | с | ||||
EOT | $ | D | d | ||||
ENQ | % | E | e | ||||
АСК | F | f | |||||
BEL | ‘ | G | g | ||||
BS | ( | H | h | ||||
НТ | ) | I | i | ||||
LF | * | J | j | ||||
VT | + | k | k | ||||
FF | , | L | i | ||||
CR | — | M | m | ||||
SO | . | N | n | ||||
SI | / | О | |||||
DEL | p | P | |||||
DC1 | Q | q | |||||
DC2 | R | r | |||||
DC3 | S | s | |||||
DC4 | T | t | |||||
NAK | U | u | |||||
SYN | V | V | |||||
ETB | w | w | |||||
CAN | X | X | |||||
EM | У | У | |||||
SUB | : | z | z | ||||
ESC | / | [ | { | ||||
FS | \ | l | |||||
GS | = | ] | } | ||||
RS | ^ | ~ | |||||
US | ? | — | n |
Символы с кодами 0…31 относятся к служебным кодам. Если эти коды используются в символьном тексте программы, они считаются пробелами. При использовании их в операциях ввода-вывода они могут иметь следующее самостоятельное значение:
Символ | Код | Значение |
BEL | Звонок; вывод на экран этого символа сопровождается звуковым сигналом | |
НТ | Горизонтальная табуляция; при выводе на экран смещает курсор в позицию, кратную 8, плюс 1 (9, 17, 25 и т.д.) | |
LF | Перевод строки; при выводе его на экран все последующие символы будут выводиться, начиная с той же позиции, но на следующей строке | |
VT | Вертикальная табуляция; при выводе на экран заменяется специальным знаком | |
FF | Прогон страницы; при выводе на принтер формирует страницу, при выводе на экран заменяется специальным знаком | |
CR | Возврат каретки; вводится нажатием на клавишу Enter (при вводе с помощью READ или READLN означает команду «Ввод» и в буфер ввода не помещается; при выводе означает команду «Продолжить вывод с начала текущей строки») | |
SUB | Конец файла; вводится с клавиатуры нажатием Ctrl-Z; при выводе заменяется специальным знаком | |
SSC | Конец работы; вводится с клавиатуры нажатием на клавишу ESC; при выводе заменяется специальным знаком |
К типу CHAR применимы операции отношения, а также встроенные функции: СНR(В) — функция типа CHAR; преобразует выражение В типа BYTE в символ и возвращает его своим значением;
UPCASE(CH) — функция типа CHAR; возвращает прописную букву, если СН -строчная латинская буква, в противном случае возвращает сам символ СН, например:
var
cl,c2: Char;
begin
cl := UpCase(‘s’) ;
c2 := UpCase (‘Ф’) ;
WriteLn(cl,’ ‘,c2)
end.
Так как функция UPCASE не обрабатывает кириллицу, в результате прогона этой
программы на экран будет выдано
S ф
Перечисляемый тип. Перечисляемый тип задается перечислением тех значений, которые он может получать. Каждое значение именуется некоторым идентификатором и располагается в списке, обрамленном круглыми скобками, например:
typе
colors =(red, white, blue);
Применение перечисляемых типов делает программы нагляднее. Если, например, в программе используются данные, связанные с месяцами года, то такой фрагмент программы:
type
ТипМесяц=(янв,фев,мар,апр,май,июн,июл,авг,сен,окт,ноя,дек);
var
месяц : ТипМесяц;
begin
…….
if месяц = авг then WriteLn(‘Хорошо бы поехать к морю!’);
…….
end.
был бы, согласитесь, очень наглядным. Увы! В Турбо Паскале нельзя использовать кириллицу в идентификаторах, поэтому мы вынуждены писать так:
type
TypeMonth=(jan,feb,mar,may,jun,jul,aug,sep,oct,nov,dec);
var
month: TypeMonth;
begin
…….
if month = aug then WriteLn(‘Хорошо бы поехать к морю!’);
…….
end.
Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение в списке получает порядковый номер 0, второе — 1 и т.д. Максимальная мощность перечисляемого типа составляет 65536 значений, поэтому фактически перечисляемый тип задает некоторое подмножество целого типа WORD и может рассматриваться как компактное объявление сразу группы целочисленных констант со значениями О, 1 и т.д.
Использование перечисляемых типов повышает надежность программ благодаря возможности контроля тех значений, которые получают соответствующие переменные. Пусть, например, заданы такие перечисляемые типы:
type
colors = (black, red, white);
ordenal= (one, two, three);
days = (monday, tuesday, Wednesday);
С точки зрения мощности и внутреннего представления все три типа эквивалентны:
ord(black)=0, …, ord(white)=2,
ord(one)=0, …ord(three)=2,
ord(monday)=0, …ord(Wednesday)=2.
Однако, если определены переменные
var
col :colors; num :ordenal;
day : days;
то допустимы операторы
col := black;
num := succ(two);
day := pred(tuesday);
но недопустимы
col := one;
day := black;
Как уже упоминалось, между значениями перечисляемого типа и множеством целых чисел существует однозначное соответствие, задаваемое функцией ORD(X). В Турбо Паскале допускается и обратное преобразование: любое выражение типа WORD можно преобразовать в значение перечисляемого типа, если только значение целочисленного выражения не превышает мощное1™ перечисляемого типа. Такое преобразование достигается применением автоматически объявляемой функции с именем перечисляемого типа (см. п. 4.4). Например, для рассмотренного выше объявления типов эквивалентны следующие присваивания:
col := one;
col := colors(0);
Разумеется, присваивание
col := 0;
будет недопустимым.
Переменные любого перечисляемого типа можно объявлять без предварительного описания этого типа, например:
var
col: (black, white, green);
Тип-диапазон. Тип-диапазон есть подмножество своего базового типа, в качестве которого может выступать любой порядковый тип, кроме типа-диапазона. Тип-диапазон задается границами своих значений внутри базового типа:
..
Здесь- минимальное значение типа-диапазона;
— максимальное его значение.
Например:
type
digit = ‘0’..’9′;
dig2= 48..57;
Тип-диапазон необязательно описывать в разделе TYPE, а можно указывать непосредственно при объявлении переменной, например:
var
date : 1..31;
month: 1. .12;
Ichr : ‘A’..’Z’;.
При определении типа-диапазона нужно руководствоваться следующими правилами:
- два символа «..» рассматриваются как один символ, поэтому между ними недопустимы пробелы;
- левая граница диапазона не должна превышать его правую границу. Тип-диапазон наследует все свойства своего базового типа, но с ограничениями, связанными с его меньшей мощностью. В частности, если определена переменная
type
days = (mo,tu,we,th,fr,sa,su);
WeekEnd = sa .. su;
var
w : WeekEnd;
begin
…..
w := sa;
…..
end;
то ORD(W) вернет значение 5 , в то время как PRED(W) приведет к ошибке.
В стандартную библиотеку Турбо Паскаля включены две функции, поддерживающие работу с типами-диапазонами:
НIGН(Х) — возвращает максимальное значение типа-диапазона, к которому принадлежит переменная X;
LOW(X) -возвращает минимальное значение типа-диапазона.
Следующая короткая программа выведет на экран строку
-32768…32767
var
k: Integer;
begin
WriteLn(Low(k),’..’,High(k))
end.
39.
Множество целых чисел бесконечно, но мы всегда можем подобрать такое число бит, чтобы представить любое целое число, возникающее при решении конкретной задачи. Множество действительных чисел не только бесконечно, но еще и непрерывно, поэтому, сколько бы мы не взяли бит, мы неизбежно столкнемся с числами, которые не имеют точного представления. Числа с плавающей запятой — один из возможных способов предсталения действительных чисел, который является компромиссом между точностью и диапазоном принимаемых значений.
Число с плавающей запятой состоит из набора отдельных разрядов, условно разделенных на знак, экспоненту порядок и мантиссу. Порядок и мантисса — целые числа, которые вместе со знаком дают представление числа с плавающей запятой в следующем виде:
Математически это записывается так:
(-1)s ? M ? BE, где s — знак, B-основание, E — порядок, а M — мантисса.
Основание определяет систему счисления разрядов. Математически доказано, что числа с плавающей запятой с базой B=2 (двоичное представление) наиболее устойчивы к ошибкам округления, поэтому на практике встречаются только базы 2 и, реже, 10. Для дальнейшего изложения будем всегда полагать B=2, и формула числа с плавающей запятой будет иметь вид:
(-1)s ? M ? 2E
Что такое мантисса и порядок? Мантисса – это целое число фиксированной длины, которое представляет старшие разряды действительного числа. Допустим наша мантисса состоит из трех бит (|M|=3). Возьмем, например, число «5», которое в двоичной системе будет равно 1012. Старший бит соответствует 22=4, средний (который у нас равен нулю) 21=2, а младший 20=1. Порядок – это степень базы (двойки) старшего разряда. В нашем случае E=2. Такие числа удобно записывать в так называемом «научном» стандартном виде, например «1.01e+2». Сразу видно, что мантисса состоит из трех знаков, а порядок равен двум.
Допустим мы хотим получить дробное число, используя те же 3 бита мантиссы. Мы можем это сделать, если возьмем, скажем, E=1. Тогда наше число будет равно
1.01e+1 = 1?21+0?20+1?2-1=2+0,5=2,5
Очевидно, что таким образом одно и то же число можно представить по-разному. Рассмотрим пример с длиной мантиссы |M|=4. Число «2» можно представить в следующем виде:
2 = 10 (в двоичной системе) = 1.000e+1 = 0.100e+2 = 0.010e+3.
Поэтому уже в самых первых машинах числа представляли в так называемом нормализованном виде, когда первый бит мантиссы всегда подразумевался равным единице.
Это экономит один бит (так как неявную единицу не нужно хранить в памяти) и обеспечивает уникальность представления числа. В нашем примере «2» имеет единственное представление («1.000e+1»), а мантисса хранится в памяти как «000», т.к. старшая единица подразумевается неявно. Но в нормализованном представлении чисел возникает новая проблема — в такой форме невозможно представить ноль.
Строго говоря, нормализованное число имеет следующий вид:
(-1)s ? 1.M ? 2E.
Качество решения задач во многом зависит от выбора представления чисел с плавающей запятой. Мы плавно подошли к проблеме стандартизации такого представления.
Статьи к прочтению:
Паскаль с нуля [ч2]. Переменные и типы данных
Похожие статьи:
-
Еще раз о типах данных в турбо паскале
Любые данные, то есть константы, переменные, значения функций или выражения, в Турбо Паскале характеризуются своими типами. Тип определяет множество…
-
Структура программы на паскале
Программы, написанные на языке программирования Турбо Паскале, строятся в соответствии с правилами, представляющими собой несколько расширенные и…