Round(5 / 0) nie wywołuje wyjątku dzielenia przez zero. Dlaczego?

0

Jak w temacie. Mam w kodzie takie wyrażenie, napisane celowo aby owy błąd wywołać:

kod := Round(5 / 0);

Jednak o dziwo EDivByZero się nie pojawia a zmienna kod (integer) po wykonaniu Round przyjmuje wartość 0. Jakieś pomysły?

0

x:=0;
y:=5/x;

1

Widocznie następuje jakaś magia i Delphi zamienia ci te liczby na floaty PRZED wykonaniem dzielenia. Zgodnie ze standardem IEEE-cośtam dzielenie przez zero skutkuje powstaniem wartości nieskończoność. Widocznie Round zamienia INFINITY na 0.

0

Ok, to działa
Jednak program nie wchodzi w obsługę wyjątku EDivByZero

try                           
 x:=0;
 y:=5/x;
 //reszta kodu
except
 on EDivByZero do
  begin
    ShowMessage('ERRRRRRRRR');
  end;
end;

Debugger wyrzuca okienku z informacją o błędzie dzielenia przez zero i po kliknięciu Continue nie przechodzi do ShowMessage('ERRRRRRRRR'); Aplikacja staje i wyświetla się okienko z komunikatem "Floating point division by zero." i po kliknięciu ok dalej stoi....

0

Rozwiązane. Zła klasa wyjątku. Wszystko jest jak powinno dla EZeroDivide.

0

try
x:=0;
y:=5 div x;
//reszta kodu
except
on EDivByZero do
begin
ShowMessage('ERRRRRRRRR');
end;
end;

0

Funkcja Round jest odporna na ten błąd, ponieważ sprawdza, czy dzielenie nie odbywa się przez zero.

  • FPC **
Var A, B, C: Integer;
Begin
 A := 5;
 B := 0;
 C := Round(A/B);
End.

Wynik: SIGFPE na Win32, FPC 2.6.0.

Var A: Integer;
Begin
 A := Round(5/0);
End.

Wynik: range check error podczas kompilacji przy wyrażeniu 5/0.

  • Delphi 7 **
    Program pierwszy: runtime error 200, czyli 'dzielenie przez zero'.
    Program drugi: Constant expression violates subrange bounds podczas kompilacji.

Czyli, jakby nie patrzeć - albo jest błąd kompilacji, albo wyjątek FPU.
0

Delphi 7

var
  x, y: Integer;
begin
  try
  y:= 0;
  x:= Round(5/y);
  except
    on E: EXception do
      ShowMessage(Format('Error: %0:s %1:s', [E.ClassName, E.Message]));
  end;
end;

user image

Jak widać następuje konwersja liczby na zmiennoprzecinkową i umieszczenie jej na stosie a później dzielenie na liczbach zmiennoprzecinkowych więc nie dziwne że wywala EZeroDivide a nie EDivByZero.

0
kAzek napisał(a)

Jak widać następuje konwersja liczby na zmiennoprzecinkową i umieszczenie jej na stosie a później dzielenie na liczbach zmiennoprzecinkowych więc nie dziwne że wywala EZeroDivide a nie EDivByZero.

Oczywiście, że tak - żeby się tego dowiedzieć wystarczyło sprawdzić klasę i komunikat wyjątku:

on E: Exception

ClassName: EZeroDivide
Message:   Floating point division by zero

No i jak byk napisane jest: Floating point;

0

Ale dlaczego w ogóle jest konwersja do liczb zmiennoprzecinkowych zamiast starej, dobrej instrukcji div?

0
Azarien napisał(a):

Ale dlaczego w ogóle jest konwersja do liczb zmiennoprzecinkowych zamiast starej, dobrej instrukcji div?

div działa tylko na operandach będących liczbami całkowitymi.

Widocznie kompilator tylko dzielenie całkowite robi div

No i poprawnie, bo tak stoi w standardzie:
6.7.2.1

Operator Operation Type of operands Type of result
div Division with truncation integer-type integer-type

1 użytkowników online, w tym zalogowanych: 0, gości: 1