delphi – 我如何使信号NaN容易使用?

前端之家收集整理的这篇文章主要介绍了delphi – 我如何使信号NaN容易使用?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
IEEE754标准定义了两类NaN,安静的NaN,QNaN和信号NaN,SNaN.当SNaN加载到浮点寄存器中时,浮点单元产生异常.

QNaN通过在Math中声明的常量名为NaN的Delphi代码可用.该常数的定义是:

const
  NaN = 0.0 / 0.0;

我想要使​​用类似的东西来声明一个常数,这是一个信号NaN,但还没有找到一个方法来做到这一点.

你可以写这段代码

function SNaN: Double;
begin
  PInt64(@Result)^ := $7FF7FFFFFFFFFFFF;//this bit pattern specifies an SNaN
end;

但是,浮点返回值的ABI意味着SNaN被加载到浮点寄存器,以便可以返回.自然会导致一个例外,而不是打败目的.

所以你被带领编写如下代码

procedure SetToSNaN(out D: Double);
begin
  PInt64(@D)^ := $7FF7FFFFFFFFFFFF;
end;

现在,这样做很有用,但这是非常不方便的.假设您需要将SNaN传递给另一个功能.理想情况下,你想写:

Foo(SNaN)

而是你必须这样做:

var
  SNaN: Double;
....
SetToSNaN(SNaN);
Foo(SNaN);

所以,在积累之后,这里是一个问题.

有没有办法写入x:= SNaN并且有浮点变量x分配一个值是一个信号NaN?

解决方法

此声明在编译时解决
const
  iNaN : UInt64 = $7FF7FFFFFFFFFFFF;
var
  SNaN : Double absolute iNaN;

编译器仍将SNaN视为常数.

尝试为SNaN分配一个值将给出编译时错误:E2064无法分配左侧.

procedure DoSomething( var d : Double);
begin
  d := 2.0;
end;

SNaN := 2.0; // <-- E2064 Left side cannot be assigned to
DoSomething( SNaN); // <--E2197 Constant object cannot be passed as var parameter
WriteLn(Math.IsNaN(SNaN)); // <-- Writes "true"

如果您有编译器指令$WRITEABLECONSTS ON(或$J),则可以临时关闭该命令,以确保不会更改SNaN.

{$IFOPT J+}
   {$DEFINE UNDEFWRITEABLECONSTANTS}
   {$J-}
{$ENDIF}

const
  iNaN : UInt64 = $7FF7FFFFFFFFFFFF;
var
  SNaN : Double ABSOLUTE iNaN;

{$IFDEF UNDEFWRITEABLECONSTANTS}
   {$J+}
{$ENDIF}

猜你在找的Delphi相关文章