gpt4 book ai didi

delphi - 如何使信号 NaN 易于使用?

转载 作者:行者123 更新时间:2023-12-03 14:41:19 27 4
gpt4 key购买 nike

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 - 如何使信号 NaN 易于使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16249748/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com