{$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