Writeln( 10/3 : 15:0); { только целая часть }
Writeln( 10/3 : 15:2); { два знака после точки }
Writeln( 10/3 : 15:3); { три знака после точки }
end.
Результат её работы таков.
3.33333333333333E+0000
3.333E+0000
3
3.33
3.333
Как говорится, лучше раз увидеть… Вывод ясен: если не указать спецификатор поля или его вторую часть, то число выводится в научном формате с плавающей точкой, а иначе – с фиксированной.
Типы вещественных чисел
Подобно целым, вещественные числа представлены несколькими типами, которые разнятся размерами и диапазонами значений. Причина разнообразия все та же – стремление сэкономить память. В табл. 3 показаны четыре типа вещественных чисел языка Паскаль.
Табл. 3 – Вещественные типы
Тип данных
Точность
Диапазон возможных значений
Количество значащих цифр (точность)
Размер в байтах
От
До
Real
Стандартная
2.9 x 10
–39
1.7 x 10
38
11-12
6
Single
Одинарная
1.5 x 10
–45
3.4 x 10
38
7-8
4
Double
Двойная
5.0 x 10
–324
1.7 x 10
308
15-16
8
Extended
Повышенная
3.6 x 10
–4951
1.1 x 10
4932
19-20
10
Но почему в колонке минимальных значений я указал не нули, а очень маленькие числа? Да, ноль допустим, но для оценки точности вычислений важно знать именно этот предел. Разумеется, что указанные диапазоны распространяются и на отрицательные числа.
Теперь исследуем точность представления чисел разными типами данных.
{ Программа для исследования точности вещественных типов }
var F0 : Real; F1 : single; F2 : double; F3 : extended;
begin
F0:= 1/3; F1:= 1/3; F2:= 1/3; F3:= 1/3;
Writeln('Single = ', F1:23:18);
Writeln('Real = ', F0:23:18);
Writeln('Double = ', F2:23:18);
Writeln('Extended= ', F3:23:18);
end.
Десятичное представление дроби 1/3 нам известно, – это бесконечная последовательность троек, а результат вычислений по этой программе перед вами (для Borland Pascal, в других компиляторах результаты могут немного отличаться):
Single = 0.333333343267440796
Real = 0.333333333333484916
Double = 0.333333333333333315
Extended= 0.333333333333333333
Как и следовало ожидать, тип Extended дает самую высокую точность, – после десятичной точки следуют одни тройки. Другие типы менее точны. Если так, зачем они нужны? Обратимся к истории.
Первые версии Паскаля ещё не застали персональных компьютеров. Тогда в языке существовал только один тип вещественных чисел – Real. Его считают стандартным типом Паскаля, и для обработки таких чисел годится любой процессор (но вычисления будут медленными).
Но вот появились компьютеры с математическими сопроцессорами, многократно ускоряющими счет. Эти сопроцессоры оперируют с форматами, отличными от Real. Для совместимости с новой техникой в язык были введены ещё три типа чисел, указанные в табл. 3. Тип Extended даёт наивысшую точность и самый широкий диапазон представления чисел. И это понятно, ведь его размер больше, чем у других, и составляет 10 байтов. Но почему он выигрывает и в скорости? А потому, что для сопроцессора тип Extended – родной, применяйте его для вычислений. А что же Single и Double? Поскольку они занимают меньше места в памяти, то лучше подходят для хранения больших объёмов данных.
Сравнение вещественных чисел
Вещественные числа часто сравнивают между собой. Однако проверка их на точное равенство таит неприятный сюрприз, – такие сравнения ненадежны! Все потому, что вещественные числа – приближенные; они могут быть очень близки, и все же чуточку не совпадать друг с другом. Точное совпадение – это удача, а не закономерность. Правильней сравнивать числа с некоторой точностью, как в показанном ниже примере.
var A, B : Extended;
...
if A = B then … { это ненадежное сравнение }
if Abs(A-B) < 0.001 then … { надежное сравнение с точностью 0.001}
Во втором сравнении переменные A и B считаются одинаковыми, если отличаются менее чем на одну тысячную. Как видите, знаком равенства тут и не пахнет. К слову, функция Abs возвращает абсолютное значение аргумента, – ведь здесь надо получить положительное значение разности. Выражение Abs(A-B) в математике пишется так: |A-B|.
Типы данных пользователя
Богатый арсенал типов данных, запасенный в Паскале, кажется достаточным на все случаи жизни. Скоро вы убедитесь, что это не так. Но Паскаль разрешает программисту создавать свои собственные типы данных, заточенные под определенную задачу. Их называют пользовательскими типами, и строят на основе все тех же базовых типов Паскаля. Рассмотрим пример.
Предположим, ваша программа содержит много переменных типа Integer. Но, по ходу работы над проектом, вы решили заменить этот тип чисел на какой-то иной, например на Longint или даже Extended. Такую замену можно сделать редактором текста, тщательно порывшись в программе и найдя все места, где объявлены переменные. Но можно сделать лучше – объявить собственный тип данных.
Для объявления пользовательских типов в Паскале служит секция описания типов, которая начинается с ключевого слова TYPE – «тип». Внутри секции можно объявить один или несколько типов данных пользователя. Так, например, вы можете объявить свой тип на базе встроенного типа Integer.
Type TValue = Integer;
Здесь объявлен тип данных по имени TValue (Value – «значение»), он равнозначен типу Integer. Как видите, объявление типа схоже с объявлением константы. Только справа от знака равенства следует не значение, а описание типа.
Имя пользовательского типа придумывают по общим правилам для имен. В свое время мы учредили префиксы для констант и аргументов процедур, – префиксы делают программу понятней. Для констант мы договорились применять префикс «C», для аргументов процедур и функций – префикс «a». Для типов возьмем префикс «T» (от слова Type). Повторяю: префиксы – это всего лишь добровольное соглашение программистов, а не требование языка.
Теперь, когда тип TValue объявлен, его можно использовать для объявления переменных, например:
Type TValue = Integer;
Var A, B, C : TValue;
...
Readln(A, B);
C:= A+B;
Если со временем потребуется изменить типы переменных A, B и C на тип Longint, то мы исправим лишь объявление пользовательского типа.
Type TValue = Longint;
И после компиляции все переменные типа TValue примут тип Longint.
На первый взгляд, пользовательские типы дают лишь косметические удобства. Но скоро – при освоении сложных типов данных – вы и шагу не ступите без них. Впрочем, пользовательские типы пригодятся нам гораздо раньше – для преобразования типов данных.
Совместимость и преобразование типов
Поздравляю! Теперь вам знакомы все простые типы данных – солдаты нашей армии. Сражаясь в едином строю, они будут передавать при необходимости данные друг другу. Такая передача данных должна подчиняться определенным правилам. Они просты, но заставляют программиста всякий раз задуматься: то ли я делаю? А это придает программам надежность.