|
Вопрос # 5 783/ вопрос решён / |
|
Здравствуйте, эксперты!
почему если сделать
var
i:real;
begin
i:=1/0;
end;
не показывается никакой ошибки типа 'division by zero'?
и в таком варианте тоже:
var
i:real;
begin
ErrorProc :=nil;
ExceptProc :=nil;
ExceptionClass :=nil;
ExceptClsProc :=nil;
ExceptObjProc :=nil;
AssertErrorProc:=nil;
i:=1/0;
end;
нужно, чтобы любые ошибки были видны.
|
Вопрос задал: Фамилия Имя Отчество (статус: Посетитель)
Вопрос отправлен: 27 ноября 2011, 06:39
Состояние вопроса: решён, ответов: 2.
|
Ответ #1. Отвечает эксперт: Толяныч
Здравствуйте, Фамилия Имя Отчество!
Не показывает, потому что никакой операции деления тут нет.
Выражение i := 1/0 присваивает переменной i максимально возможное положительное значение. Если посмотреть отладчиком, то в i увидим +INF .
Вот цитата из хелпа по запросу "Infinity constant".
<
Unit
Math
Category
Arithmetic routines
Delphi syntax:
const Infinity = 1.0 / 0.0;
Description
Use Infinity to assign a value of positive Infinity to a floating-point variable. Do not use Infinity in comparisons. To check whether a variable or expression represents infinity, use the IsInfinite function instead.
Represents positive infinity.
>
Чтоб получить ожидаемую реакцию, нужно :
a := 0.0 ; i := 1.0/a ;
Странноватый выбор идентификатора i для real. Но это так, к слову...
|
Ответ отправил: Толяныч (статус: 4-ый класс)
Время отправки: 27 ноября 2011, 23:07
Оценка за ответ: 4
Комментарий к оценке: ничего не изменилось, всё равно никакой ошибка не показывает...
procedure TForm1.Button1Click(Sender: TObject);
var
a,b,c:real;
begin
a:=0.0;
b:=1.0;
с:=b/a;
end;
|
Ответ #2. Отвечает эксперт: Егор
Здравствуйте, Фамилия Имя Отчество!
Правы все эксперты.
Поясню на примерах:
1) procedure TForm1.Button1Click(Sender: TObject);
var
z : real;
begin
z := 1 / 0;
end;
Программа откомпилируется и будет работать. Выражение 1/0 будет вычислено компилятором (об этом ниже), но затем, на фазе оптимизации, т.к. переменная z не используется, то компилятор выкинет любые упоминания этой переменной. Ошибка не возникнет.
2) procedure TForm1.Button1Click(Sender: TObject);
var
z : real;
begin
z := 1 / 0;
showmessage(floattostr(z)); // выдаст INF
end;
Программа откомпилируется и будет работать. Выдаваться будет INF, т.к. для дробных чисел предусмотрено специальное значение - бесконечность (INF). Значение это будет вычислено компилятором до запуска программы, а в текст будет подставлено именно значение INF, а не выражение 1/0.
Аналогично можно записать z := infinity; (должен быть подключен модуль Math).
3) procedure TForm1.Button2Click(Sender: TObject);
var
x, y, z : real;
begin
x := 1;
y := 0;
z := x / y; // ошибка выполнения:
// Project Project1.exe raised exception class EZeroDivide
// with message 'Floating point division by zero'.
// Process stopped. Use Step or Run to continue.
showmessage(floattostr(z));
end;
Здесь произойдёт ошибка времени выполнения. Во время работы программы будет выдано сообщение "Floating point division by zero".
4) procedure TForm1.Button3Click(Sender: TObject);
var
a, b, c : integer;
begin
a := 1;
b := 0;
c := a div b; // ошибка выполнения:
// Project Project1.exe raised exception class EDivByZero
// with message 'Division by zero'.
// Process stopped. Use Step or Run to continue.
showmessage(inttostr(c));
end;
Т.к. числа целые (integer), то использовать операцию деления (/) нельзя. Вместо неё используется операция целочисленного деления (div).
Во время работы программы будет выдано сообщение об ошибке деления на ноль: "Division by zero".
5) procedure TForm1.Button4Click(Sender: TObject);
var
c : integer;
begin
c := 1 div 0; // не скомпилируется
showmessage(inttostr(c));
end;
Этот вариант не скомпилируется вообще, т.к. здесь идёт попытка заставить компилятор разделить нацело целое число на ноль.
5) procedure TForm1.Button4Click(Sender: TObject);
var
c : integer;
begin
c := 1 div 0; // не скомпилируется
end;
Несмотря на то, что переменная с не используется, этот вариант также не скомпилируется. Причина - у нас есть выражение (1 div 0), которое надо вычислить. Вычисление будет выполнено до фазы оптимизации, поэтому процесс компиляции не будет успешным.
P.S. Все варианты проверялись в Delphi7.
|
Ответ отправил: Егор (статус: 10-ый класс)
Время отправки: 28 ноября 2011, 16:54
Оценка за ответ: 5
Комментарий к оценке: Спасибо за информацию.
|
Мини-форум вопроса
Всего сообщений: 5; последнее сообщение — 29 ноября 2011, 00:51; участников в обсуждении: 4.
|
min@y™ (статус: Доктор наук), 27 ноября 2011, 09:10 [#1]:
Цитата (Фамилия Имя Отчество):
не показывается никакой ошибки типа 'division by zero'?
Может компайлер просто выкинул эту операцию, т.к. переменная i больше не используется?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Фамилия Имя Отчество (статус: Посетитель), 28 ноября 2011, 13:58 [#2]:
>>Может компайлер просто выкинул эту операцию, т.к. переменная i больше не используется?
procedure TForm1.Button1Click(Sender: TObject);
var
a,b,c,d:real;
begin
a:=0.0;
b:=1.0;
c:=b/a;
d:=c;
end;
тоже не работает
|
|
Вадим К (статус: Академик), 28 ноября 2011, 14:48 [#3]:
это оптимизации.
Попробуйте написать так
procedure TForm1.Button1Click(Sender: TObject);
var
a,b,c,d:real;
begin
a:=0.0;
b:=1.0;
c:=b/a;
d:=c;
showmessage(floattostr(d));
end;
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Фамилия Имя Отчество (статус: Посетитель), 29 ноября 2011, 00:51 [#5]:
Вариант, подсказанный Вадимом работает!
Спасибо.
|
9 декабря 2011, 14:42: Статус вопроса изменён на решённый (изменил автор вопроса — Фамилия Имя Отчество): Ура! Мне дали награду за лучший вопрос месяца! Надо отметить!
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|