德尔福柏林10.1分零缺失异常

Doe*_*ege 5 delphi exception delphi-10.1-berlin

我很惊讶没有得到除零异常.我怎样才能找回来?

柏林10.1最近安装,新项目,

procedure TForm1.Button1Click(Sender: TObject);
var
  a: Double;
begin
  a := 5/0;                     // No exception
  ShowMessage(a.ToString);      // -> 'INF'
end;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 7

a := 5/0;
Run Code Online (Sandbox Code Playgroud)

5/0技术语言的角度来看,表达式是一个常量表达式.

常量表达式是编译器可以在不执行其发生的程序的情况下进行求值的表达式.常量表达式包括数字; 字符串; 真常数; 枚举类型的值; 特殊常量True,False和nil; 和表达式专门使用运算符,类型转换和集合构造函数构建的表达式.

因此,此表达式由编译器评估,而不是在运行时.因此,它的评估由编译时规则决定,不受运行时浮点单元异常掩码的影响.

这些规则规定正值除以零等于+INF特殊的IEEE754值.如果将表达式更改为至少有一个不是常量表达式的参数,那么它将在运行时进行计算,并且将引发除零异常.


Vil*_*nde 5

您可以使用数学单元中的 SetExceptionMask 函数控制触发哪些浮点异常:http ://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Math.SetExceptionMask

要禁用所有浮点异常,请使用:

SetExceptionMask(exAllArithmeticExceptions);
Run Code Online (Sandbox Code Playgroud)

要启用所有浮点异常,请使用:

SetExceptionMask([]);
Run Code Online (Sandbox Code Playgroud)

另请注意,在您的示例代码中,编译器将在编译时确定该值(因为表达式是常量),因此无论传递给 SetExceptionMask 的值如何,它都不会触发异常。要触发异常,您需要一个稍微复杂的示例,如下所示:

program test;
uses Math;
var
  xx,yy: double;
begin
SetExceptionMask([]);
xx := 1;
yy := 0;
halt(round(xx/yy));
end.
Run Code Online (Sandbox Code Playgroud)

  • @DavidHeffernan 在关于不触发浮点异常的讨论中,我认为提及 SetExceptionMask 是相关的。当然,这可能不是 OP 代码中的原因,但是这里发布的代码经常被简化太多,而真正的代码可能使用了变量。 (5认同)
  • 至少这个答案的第一部分与提出的问题无关 (3认同)