Преобразование
типов иногда вызывает легкий шок.
Вычисляешь, например, расстояние между
точками плоскости:
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 и
даёт такой результат (В броузере ВЫ
можете увидеть искаженную
автоматическим переносом программу;
просто скопируйте её в блокнот,
положение с переносом исправится).