Множество действительных чисел в ТП представлено вещественными типами. За одним исключением, все они обладают определенной погрешностью при проведении арифметических операций.

Таблица свойств вещественных типов данных:

Вещественный тип

Диапазон возможных значений

Значащие цифры

Размер в байтах

Real

type

11-12

6

Single

image056.gif

7-8

4

Double

image058.gif

15-16

8

Extended

image060.gif

19-20

10

Comp

image062.gif

19-20

8

Для типов Real, Single, Double и Extended в диапазон значений включается и отрицательная область.

Если компьютер не имеет встроенного математического сопроцессора, то удобнее всего использовать тип Real, так как разработчики ТП специально для него оптимизировали по скорости все операции. Остальные 4 типа являются специфичными для математического сопроцессора и должны использоваться с директивой компилятора {$N+}, которая указывает на его присутствии в системе, где будет исполняться программа. При отсутствии сопроцессора, с помощью директивы {$N+,E+} можно произвести его эмуляцию и применять в программе все вещественные типы.

Директива {$N+} замедляет скорость вычислений с типом Real, который является специфическим для ТП и не поддерживается сопроцессором. Таким образом, арифметические операции с типом Real предваряются переводом Real в Extended и завершаются обратным переводом.

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

Тип Comp на самом деле не является вещественным. Это целочисленный тип с очень большим диапазоном значений (примерно от -1018 до 1018). Его удобно использовать в бухгалтерских расчетах, когда производятся операции над гигантскими суммами и требуется вести учет до последней копейки. Математический сопроцессор обрабатывает тип Comp методами, аналогичными для других вещественных типов.

Следующий пример отвечает на вопрос о точности вычислений для различных вещественных типов:

Задача 25. Вычислить выражение image064.gif двумя способами:

1) последовательно слева направо

2) последовательно слева направо вычисляются image066.gif, затем type, после чего второе значение вычитается из первого.

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

Решение:

var s,s1,s2,s3:real;

i,sign:integer;

begin

{----- ПЕРВЫЙ способ -----}

s:=0;

sign:=1; {значение, с помощью которого меняется знак перед слагаемым}

for i:=1 to 100 do begin

s:=s+sign/i; {вычисляем сумму}

sign:=-sign; {меняем знак}

end;

{----- ВТОРОЙ способ -----}

s1:=0;

for i:=1 to 50 do s1:=s1+1/(i*2-1);{вычисляем сумму с нечетным знаменателем}

s2:=0;

for i:=1 to 50 do s2:=s2+1/(i*2);{вычисляем сумму с четным знаменателем}

s3:=s1-s2;{вычисляем разность между полученными значениями }

writeln(s);

writeln(s3);

writeln(s-s3);

readln;

end.

В результате выполнения программы на экране появятся 3 числа:

6.8817217931E-01

6.8817217931E-01

-9.0949470177E-12

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

Применим директиву компилятора {$N+, E+}, чтобы проанализировать работу программы при использовании математического сопроцессора. ($N - для подключения сопроцессора, $E - для эмуляции в случае его отсутствия):

{$N+, E+}

var s,s1,s2,s3:real;

i,sign:integer;

begin

...

Результат:

6.88172179303365E-0001

6.88172179314279E-0001

-1.09139364212751E-0011

Последовательно заменяя тип Real в программе на типы Single, Double и Extended получим следующие значения:

Для типа Single:

6.88171803951263E-0001

6.88172578811646E-0001

-7.74860382080078E-0007

Для типа Double:

6.88172179310196E-0001

6.88172179310195E-0001

3.33066907387547E-0016

Для типа Extended:

6.88172179310195E-0001

6.88172179310195E-0001

6.50521303491303E-0019

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

Вещественный тип можно преобразовать в порядковый (а конкретно - в целочисленный) с помощью двух функций:

function Round(X: Real): Longint;

function Trunc(X: Real): Longint;

Функция Round производит округление переданного ей вещественного значения до ближайшего целого.

Например:

Begin

Write(round(1.3),' ', round(2.7),' ', round(-7.3),' ', round(-15.5));

End.

В результате выполнения этой программы на экране появится строка, состоящая из 4 чисел: 1 3 -7 -16

Функция Trunc производит отбрасывание дробной части у переданного ей вещественного значения.

Например:

Begin

Write(trunc(1.3),' ', trunc(2.7),' ', trunc(-7.3),' ', trunc(-15.5));

End.

В результате выполнения этой программы на экране появится строка, состоящая из 4 чисел: 1 2 -7 -15

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

Для простых, с небольшим объемом вещественных расчетов используйте тип Real.

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

Если объем памяти ограничен или требуется обработка больших вещественных массивов, и при этом точность вычислений не играет особой роли, используйте тип Single.

В ситуации, промежуточной между первыми двумя, используйте тип Double.

Если Вы выполняете расчеты с очень большими целыми числами, используете тип Comp.

Если у Вас отсутствует математический сопроцессор, а скорость выполнения программы играет решающую роль, используйте тип Real.

<- Предыдущая страница | Следующая страница ->
Последнее изменение: Вторник 1 Март 2011, 16:58