Программирование в среде Турбо Паскаль (Поляков, Круглов) - страница 118

{$ELSE>

TYPE

Float = Real; { без 80X87 — только этот тип }

{SENDIF}

VAR { переменные типа Float }

r : Float;

d : Array [1..9] of Float;

Целые типы Турбо Паскаля работают с сопроцессором без каких-либо оговорок.

Особо важным является вопрос точности вычислений. При использовании сопроцессора все стандартные математические операторы и функции языка, возвращающие обычно значения Real, начинают возвращать значения типа Extended. В связи с этим имеет смысл опираться именно на этот тип как базовый. Тем не менее вполне возможно, что в программе будут участвовать переменные разных типов. В таких случаях при необходимости будет производиться преобразование значений, а значит, потеря точности. При вычислении значений правых частей операторов присваивания результат имеет точность, совпадающую с наиболее точным из типов членов выражения (или, что то же самое, с наиболее емким типом). Это означает, что в присваивании

VAR

e1, e2 : Extended;

e3 : Double;

result : Single;

...

result := e1*e2/e3;

- 184 -

значение выражения справа будет вычислено как тип Extended. Но при присваивании его переменной result «малого» типа Single будет произведено усечение, и резко уменьшится число значащих цифр после десятичной точки. Подобные ситуации надо предвидеть и стараться избегать их. Особенно неприятны они в циклах суммирования:

VAR

е : Extended:

Sum : Single;

i : Word;

...

BEGIN

e:=1.23456e-12;

Sum:=0;

for i:=32767 to 65535 do Sum := Sum + i/e;

...

END.

Здесь подобные потери будут повторены тысячи раз, и накопленная ошибка может быть соизмерима с самой суммой. Исправить ситуацию легко: надо ввести дополнительную переменную eSum точного типа Extended для сумматора, и переписать цикл:

eSum:=0;

for i:=32767 to 65535 do eSum := eSum + i/e;

Sum:=eSum;

Теперь потери будут значительно меньше.

По той же причине (из-за усечения точности) некорректной является операция сравнения двух разнотипных вещественных переменных или переменной с выражением (последнее, как уже отмечалось, может быть вычислено в типе Extended). Так, сравнение в примере:

VAR

e : Extended;

d : Double;

...

e := Cos( Pi/8 );

d := e;

{==>} if d=e then ...

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

- 185 -

равными. Так, условие if в последнем примере следовало бы переписать так:

if Abs(d-e) < 1.0Е-15 then