Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Встроенные типы данных. Целые типы. Представление знака числа. Арифметическое переполнение





Встроенные типы данных

Любой реально существующий тип данных, каким бы сложным он ни казался на первый взгляд, представляет собой простые составляющие (базовые типы), которые, как правило, всегда присутствуют в языке программирования (отсюда и происходит название «встроенные типы данных»). Они не требуют дополнительного описания и представляются соответствующими операторами. В Object Pascal к таким составляющим относятся простые типы данных, которые, в свою очередь, делятся на:

- порядковые типы;

- вещественные типы;

- типы дата-время.

Каждый из порядковых типов имеет конечное число значений. Следовательно, их можно упорядочить и с каждым из них сопоставить порядковый номер значения.

Вещественные представляют приближенно математические вещественные числа. Разделение типов на порядковые и вещественные несколько условно, т.к., строго говоря, вещественные тоже имеют конечное число значений. Количество значений определяется форматом внутреннего представления вещественного числа и настолько велико, что сопоставить порядковый номер с каждым значением практически невозможно.

Тип дата-время используется для хранения даты и времени.

Из простых типов данных порядковые - самые простые. В этих типах информация представляется в виде отдельных элементов.

В Object Pascal к порядковым типам относятся:

- целые типы;

- символьный тип;

- логические типы;

- задаваемые пользователем перечисления;

- тип-диапазон.

Все значения любого порядкового типа образуют упорядоченную последовательность, и значение переменной порядкового типа определяется его местом в этой последовательности. За исключением переменных целых типов, значения которых могут быть как положительными, так и отрицательными.



Первый элемент любого порядкового типа имеет номер 0, второй элемент - номер 1 и т.д. Порядковый номер значения возвращает функция Ord():

- если х представляет собой целое значение, то порядковый номер равен самому значению. Иными словами, для целых типов Ord(x)=x.

- если х представляет собой логический тип, то функция Ord(x) возвращает положительное целое число от 0 до 1;

- если х представляет собой символьный тип, то функция Ord(x) возвращает положительное целое число от 0 до 255;

- если х представляет собой перечисляемый тип, то функция Ord(x) возвращает положительное целое число от 0 до 65535.

- если х представляет собой поддиапазон, то значение, возвращаемое функцией Ord(x), зависит от базового типа. Это связано с тем, что поддиапазон сохраняет свойства порядкового типа, от которого он образован.

 

К порядковым типам также применяются функции Pred(x) и Succ(x).

Результатом вызова функции Pred(x) является предыдущее значение порядкового типа. Другими словами, Pred(x) = Ord(x) - 1.

В свою очередь, Succ(x) возвращает следующее значение порядкового типа, т.е. Succ(x) = Ord(x) + 1.

 

Если программа будет содержать такие строки:

 

procedure TForml.BitBtnlClick(Sender: TObject);

var

ch:Char;

 

begin

ch:='с';

Pred(ch);

Succ(ch);

end;

 

то Pred(ch) вернет символ 'b', a Succ (ch) - символ 'd'.

По объективным причинам далее не будут рассматриваться перечисляемый тип и тип-диапазон, относящиеся к порядковым типам, т.к. они являются более развитыми элементами Object Pascal. Но оставлять их без внимания все же не следует. Поэтому мы изучим их менее подробно, чем остальные простые типы.

При задании перечисляемого типа программист просто явно указывает (перечисляет) все значения, которые может принимать переменная такого типа. Например, рассмотрим следующие «перечисления»:

TYPE Tcolor=(red, green, blue);

TDay=(Sun, Mon, Tue, Wed, Thu, Fri, Sat);

 

Здесь создаются два новых типа данных. Переменная типа Tcolor сможет принимать лишь три значения: red, green, blue, а переменная типа TDay – значения Sun, Mon, Tue, Wed, Thu, Fri, Sat. Слова red, green, blue представляют собой константы, за которыми на самом деле скрываются некоторые числовые значения. Но нам в программе гораздо удобнее работать со словами, чем с числами. Было бы очень неудобно закодировать цвета цифрами и мучительно вспоминать, что "0" – это красный цвет, а "2" – синий.

Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение в списке получает порядковый номер 0, второе - 1 и т. д. Т.е. значения в перечислимом типе упорядочены по возрастанию. Поэтому их можно сравнивать не только на равенство, но и на отношения "больше - меньше".

Для работы с переменными перечислимого типа предназначены следующие функции и процедуры:

 

INC(v) – записать в v следующее значение;

DEC(v) - записать в v предыдущее значение.

 

Например:

 

c:Tday;

...

c:=Mon;

INC(c); {теперь c=Tue}

 

Обратите внимание, что эти процедуры меняют значение переменных, подаваемых им на вход в качестве аргументов. Если это нежелательно, следует использовать функции:

 

PRED(v) – предыдущее значение перечислимого типа;

SUCC(v) – последующее значение перечислимого типа.

 

Например:

c1:=PRED(c); {c1=Sun}

c2:=SUCC(c); {c2=Mon}

 

Тип-диапазон является производным типом. Он базируется на некотором базовом порядковом типе (исключая тип-диапазон). Ограниченный тип, или тип-диапазон, действительно ограничивает значения переменной. Например, если в переменной day хранится число дней в месяце, то оно явно не должно превышать 31, а также быть меньше 1. Следовательно, диапазон допустимых значений этой переменной – [1..31]. Так и напишем:

 

TYPE Tdate=[1..31]

 

Транслятор при работе программы проверяет, попадает ли значение переменной в допустимый диапазон. При выходе за его границы выдается сообщение об ошибке. Разумеется, это заметно повышает надежность программ.

Важно отметить, что в памяти переменная ограниченного типа занимает ровно столько же места, сколько и переменная базового типа. Поэтому сэкономить память, применяя поддиапазоны, не удастся.

 

В стандартную библиотеку Object Pascal включены две функции, поддерживающие работу с типами-диапазонами:

- High(X) - возвращает максимальное значение типа-диапазона, к которому принадлежит переменная х;

- Low (X) - возвращает минимальное значение типа-диапазона, к которому принадлежит переменная х.

 

Целые типы

Диапазон возможных значений целых типов зависит от их внутреннего представления, которое может занимать один, два, четыре или восемь байтов.

В табл.7 приведены характеристики целых типов языка программирования Object Pascal. Они различаются диапазоном допустимых значений и размером занимаемой памяти.

Таблица 7 - Целые типы

Название Диапазон значений Размер, байт
Byte 0...255
ShortInt -128...+127
SmallInt -32 768...+32 767
Word 0...65 535
Integer -2 147 483 648...+2 147 483 647
LongInt -2 147 483 648...+2 147 483 647
LongWord 0...4 294 967 295
Int64 -9e18...+9e18
Cardinal 0...2 147 483 647

Примечание: Типы LongWord и Int64 впервые введены в Delphi версии 4, а типы SmallInt и Cardinal отсутствуют в Delphi 1. Тип Integer для Delphi 1 занимает 2 байта и имеет диапазон значений от -32768 до +32767, т.е. совпадает с SmallInt из Delphi 4.

 

Значения целых типов в программе могут изображаться в десятичном и шестнадцатеричном виде.

При действиях с целыми числами тип результата будет соответствовать типу операндов, а если операнды относятся к различным целым типам - общему типу, который включает в себя оба операнда. Например, при действиях с ShortInt и Word общим будет тип Integer.

 

Представление знака числа

Многие числовые поля не имеют знака, например, номер абонента, адрес памяти. Некоторые числовые поля предлагаются всегда положительные, например, норма выплаты, день недели, значение числа ПИ. Другие числовые поля являются знаковые, так как их содержимое может быть положительным или отрицательным. Например, алгебраическое число или долговой баланс покупателя, который может быть отрицательным при переплатах.

Для беззнаковых величин все биты являются битами данных и вместо ограничения +32767 переменная может содержать числа до +65535. Для знаковых величин левый (старший) бит является знаковым битом.

Таким образом:

- унарный знак + (плюс), поставленный перед параметром целого или вещественного типа, никак не влияет на его значение.

- унарный знак - (минус), поставленный перед параметром целого или вещественного типа, приводит к изменению знака величины.

 

В следующем примере сложения двух двоичных чисел, первое число содержит единичный левый бит. Для беззнакового числа биты представляют положительное число 249, для знакового - отрицательное число -7:

  Беззнаковое Знаковое
-7
+2
-5

Двоичное представление результата сложения одинаково для беззнакового и знакового числа. Однако биты представляют +251 для беззнакового числа и -5 для знакового. Таким образом, числовое содержимое поля может интерпретироваться по-разному.

 

Арифметическое переполнение

Арифметическое переполнение (arithmetic overflow) - потеря значащих цифр при вычислении значения выражения.

Если в переменной можно хранить лишь неотрицательные значения (типы BYTE и WORD), то попытка записи в них отрицательного значения не вызовет ошибки. Возникнет арифметическое переполнение и в переменной окажется положительное значение, равное разности между максимально возможным числом комбинаций для этой переменной (256 или 65536 соответственно) и записываемым в нее отрицательным значением. Например, если в переменную a типа BYTE в результате вычислений записывается -20, то реально в ней окажется значение 256-20=236. Аналогичная ситуация возникает при записи слишком больших чисел – значение переменной проходит через ноль и начинает отсчет сначала. Так, при занесении значения 300 в переменную типа BYTE ее значением окажется 300-256=44.

Приведем другой пример: в стандартной настройке компилятор Delphi не вырабатывает код, осуществляющий контроль возможного выхода значения за границы допустимого диапазона, что может привести к недоразумениям. Например, при прогоне следующей программы на экране появится значение 0:

 

procedure TfmExample.bbRunClick(Sender: TObject);

var

k:Word;

 

begin

k:=65535; // Максимальное значение типа Word

k:=k+1; // По правилам математики k=65536

IbOutput.Caption:=IntToStr(k); // На самом деле k=0!

end;

 

Если активизировать переключатель project | options | Compiler | Range checking и повторить компиляцию с помощью Project | Build All, компилятор вставит в программу код проверки переполнения и при прогоне программы возникнет исключительная ситуация, которую при желании можно соответствующим образом обработать. Заметим, что, если изменить программу следующим образом:

 

k:=65535; // Максимальное значение типа Word

//На экран будет выведено значение 65536

IbOutput.Caption:=IntToStr(k+1);

 

переполнения не произойдет, т.к. 32-разрядный компилятор версий Delphi 32 автоматически преобразует операнды выражения k+i к 4-байтным величинам.

 

Еще хуже ситуация складывается при возникновении арифметического переполнения у переменных со знаком – при этом самопроизвольно меняется знак числа.

Обычно сложение чисел со знаком дает верный результат. Однако при возникновении арифметического переполнения при сложении знаковых чисел, результат получается неправильный.

Следующий пример - сложение двух 8-битовых чисел, представленных в двоичном коде, - иллюстрирует этот случай:

  Беззнаковое Знаковое
+121
+11
-124
    (неправильно)

Сложение положительных чисел никогда не дает в результате отрицательного числа.

Результат сложения оказался непредставимым в диапазоне значений 8-битовых чисел в двоичном коде (от -128 до +127).

Также возможен случай одновременного арифметического переполнения беззнакового и знакового чисел:

  Беззнаковое Знаковое
-10
-119
+127
  (неправильно) (неправильно)

 









Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2019 zdamsam.ru Размещенные материалы защищены законодательством РФ.