А. Григорьев - О чём не пишут в книгах по Delphi
- Название:О чём не пишут в книгах по Delphi
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2008
- Город:СПб
- ISBN:978-5-9775-019003
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
А. Григорьев - О чём не пишут в книгах по Delphi краткое содержание
Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.
Для программистов
О чём не пишут в книгах по Delphi - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Получается, что в ситуации, когда использование беззнакового типа кажется вполне безобидным (действительно, индексы списка не могут быть отрицательными), нас подстерегает "подводный камень", связанный с тем. что верхняя граница цикла может оказаться отрицательной и будет неявно приведена к большому положительному числу. Поэтому в цикле предпочтительнее переменная знакового типа Integer
, а если по каким-то причинам приходится использовать переменную типа Cardinal
, то необходимо внимательно следить за тем, какие значения принимают границы типа.
Строго говоря, аналогичная проблема может возникнуть и со знаковыми типами, если границы цикла for переходят допустимый диапазон этих чисел, просто циклы, переменная которых принимает значения вблизи границ диапазона типа Integer
, встречаются гораздо реже.
3.2. Неочевидные особенности вещественных чисел
Если рассмотренные в предыдущих разделах особенности целых чисел могли быть неочевидными только начинающим, то вещественные числа могут преподнести сюрпризы даже достаточно опытным программистам, т.к. их поведение существенно дальше от интуитивных представлений, и эти неожиданности не ограничиваются выходом та пределы диапазона. Существующая литература по Delphi, в основном, считает этот вопрос несущественным и обходит его стороной, в результате чего программист, впервые столкнувшийся с одним из таких сюрпризов, впадает в недоумение и испытывает желание "попрыгать вокруг компьютера с бубном". Здесь мы попытаемся восполнить этот пробел и показать, что необъяснимые на первый взгляд явления на самом деле просты и предсказуемы, если известно, как реализуется вещественная арифметика компьютером.
3.2.1. Двоичные дроби
Для начала — немного математики. В школе мы проходим два вида дробей простые и десятичные. Десятичные дроби, по сути дела, представляют собой разложение числа по степеням десяти. Так, запись 13,6704 означает число, равное 1·10 1+ 3·10 0+ 6·10 -1+ 7·10 -2+ 0·10 -3+ 4·10 -4. Но внутреннее представление всех чисел в компьютере, в том числе и вещественных, не десятичное, а двоичное. Поэтому он использует двоичные дроби. Они во многом похожи на десятичные, но основанием степени у них служит двойка. Так, двоичная дробь 101.1101 — это 1·2 2+ 0·2 1+ 1·2 0+ 1·2 -1+ 1·2 -2+ 0·2 -3+ 1·2 -4. В десятичном представлении это число равно 5,8125, в чем нетрудно убедиться с помощью любого калькулятора.
Теперь вспомним научный формат записи десятичного числа. Первым в этой записи идет знак числа (плюс или минус). Дальше идет так называемая мантисса (число от 1 до 10). Затем идет экспонента (степень десяти, на которую надо умножить мантиссу, чтобы получить нужное число). Итак, уже упоминавшееся число 13,6704 запишется в этом формате как 1.36704·10 1(или 1.36704E1 по принятым в компьютере правилам). Если записываемое число меньше единицы, экспонента будет отрицательной. Аналогичная запись существует и в двоичной системе. Так, 101.1101 запишется в виде 1.011101*10 10(везде использована двоичная форма записи, так что 10 10означает 2 2). Именно такое представление реализовано в компьютере. Двоичная точка в такой записи не остается на одном месте, а сдвигается на величину, указанную в экспоненте, поэтому такие числа называются числами с плавающей точкой (floating point numbers).
3.2.2. Вещественные типы Delphi
В Delphi существует четыре вещественных типа: Single
, Double
, Extended
и Real
. Их общий формат одинаков (рис. 3.1, а).
Знак — это всегда один бит. Он равен нулю для положительных чисел и единице для отрицательных. Что же касается размеров мантиссы и экспоненты, то именно в них и заключается различие между типами.
Прежде чем перейти к конкретным цифрам, рассмотрим подробнее тип Real
, сделав для этого небольшой экскурс в историю. Real
— это стандартный тип языка Паскаль, присутствовавший там изначально. Когда создавался Паскаль, процессоры еще не имели встроенной поддержки вещественных чисел, поэтому все операции с данными типа Real сводились к операциям с целыми числами. Соответственно, размер полей в типе Real
был подобран так, чтобы оптимизировать эти операции.
а) общий вид вещественного числа

б) Двоичное представление числа типа Single

Рис. 3.1.Хранение вещественного числа в памяти
Микропроцессор Intel 8086/88 и его улучшенные варианты — 80286 и 80386 — также не имели аппаратной поддержки вещественных чисел. Но у систем на базе этих процессоров была возможность подключения так называемого сопроцессора. Эта микросхема работала с памятью через шины основного процессора и обеспечивала аппаратную поддержку вещественных чисел. В системах средней руки гнездо сопроцессора обычно было пустым, т.к. это уменьшало цену (разумеется, вставить туда сопроцессор не было проблемой). Для каждого центрального процессора выпускались свои сопроцессоры, маркировавшиеся Intel 8087, 80287 и 80387 соответственно. Были даже сопроцессоры, выпускаемые другими фирмами. Они работали быстрее, чем сопроцессоры Intel, но появлялись на рынке позже. Тип вещественных чисел, поддерживаемый сопроцессорами, не совпадает с Real
. Он определяется стандартом IEEE (Institute of Electrical and Electronics Engineers).
Чтобы обеспечить в своих системах поддержку типов IEEE, Borland вводит в Turbo Pascal типы Single
, Double
и Extended
. Extended
— это основной для сопроцессора тип, a Single
и Double
получаются из него очень простым усечением. Система команд сопроцессора допускает работу с этими типами: при загрузке числа типа Single
или Double
во внутренний регистр сопроцессора последний конвертирует их в Extended
. Напротив, при выгрузке чисел этих типов из регистра в память сопроцессор усекает их до нужного размера. Внутренние же операции всегда выполняются с данными типа Extended
(впрочем, из этого правила есть исключение, на котором мы остановимся позже, после детального рассмотрения формата различных типов). Single
и Double
позволяют экономить память. Ни один из них также не совпадает с типом Real
. В системах с сопроцессорами новые типы обрабатываются заметно (в 2–3 раза) быстрее, чем Real
(это с учетом того, что тип Real
после соответствующего преобразования также обрабатывался сопроцессором; если же сравнивать обработку типа Extended
на машине с сопроцессором и Real
на машине без сопроцессора, то там на отдельных операциях достигалась разница в скорости примерно в 100 раз). Чтобы программы с этими типами можно было выполнять и в системах без сопроцессора, была предусмотрена возможность подключать к ним программный эмулятор сопроцессора. Обработка этих типов эмулятором была медленнее, чем обработка Real
.
Интервал:
Закладка: