Преобразование типов в Паскале иногда удивляет. Решаем задачку о нахождении расстояния между двумя точками плоскости. Все просто и понятно. А программа дает ошибку!
var x1,y1,x2,y2,dx,dy:integer;d:real;
begin
x2:=520;y2:=200;
x1:=320;y1:=200;
dx:=x2-x1;
dy:=y2-y1;
d:=dx*dx+dy*dy;{???}
d:=sqrt(d);{!!!}
end.
Ошибка при вычислении возникает из-за того, что промежуточная переменная при вычислении выражения {???} берётся того же типа, что и операнды, т.е.INTEGER, и вычисления производятся с отбрасыванием старших разрядов, что и приводит к появлению отрицательного знака.
Попробуйте выполнить эту программу, установив точки останова на строках {!!!}. Вы с удивлением обнаружите, что остановки происходят не всегда, хотя переменные примают эти значения (можете установить курсор на строку y:=0; , нажимать <F4> и смотреть в окне Watches !!!)
var x,y:real;
begin
x:=0;
repeat
y:=0;
repeat
if (x=0.5)and(y=0.5)
then
begin
writeln(x:1:1,' ',y:1:1);{!!!}{1}
end;
if (x=1)and(y=0)
then
begin
writeln(x:1:1,' ',y:1:1);{!!!}{2}
end;
y:=y+0.1;
until y>2;
x:=x+0.1;
until x>2;
end.
Несмотря на все ВАШИ старания остановки в точке {2} не происходит. Это объясняется тем, что при действиях с числами вещественого типа вычисления происходят приблизительно с точностью до 12 знака после первой значащей цифры.
В документации фирмы Borland процедура Val описана так:
procedure Val(S; var V; var Code: Integer);
где: S- переменная строкового типа; должна быть последавательностью символов, формирующей число; V -переменная целого или вещественного типа; Code -переменная типа Integer.
Так же сказано, что переменная Code содержит номер первого ошибочного символа. Но в случае, подобном Val('1E+E',V,Code); значение переменной Code станет равно не 2, как кажется, а 4, т.е. ошибочно не присутствие 'E+' после 1, а отсутствие показателя в экспоненциальной форме записи числа.
Трассировка при отладке, что может быть проще! Нажимаешь <F7> и смотришь все операторы по ходу выполнения. И в прочедуры с функциями заглядываешь. Это так, но не всегда. В приведённой ниже программе достаточно нажать <F7> 2 раза и она выполнитя вся.
procedure mainproc;procedure pr1;begin end;begin
writeln('А нету трассировки!!!');
writeln('Посмотри по <Alt-F5>!!!');
writeln('Думай, почему!!!');
end;
begin mainproc;
end.
В программе важно расположение по строкам, т.к. именно положение begin для процедуры mainproc на однои строке с дополнительной процедурой pr1 и даёт такой результат (В броузере ВЫ можете увидеть искаженную автоматическим переносом программу; просто скопируйте её в блокнот, положение с переносом исправится).