本文介绍了如何使信号NaN容易使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 IEEE754标准定义了两类NaN,安静的NaN,QNaN和信号NaN,SNaN。当SNaN加载到浮点寄存器中时,浮点单元会产生异常。 QNaN通过名为 Math 中声明的c> NaN 。该常量的定义是: const NaN = 0.0 / 0.0; 我想要使用类似的东西来声明一个常数,这是一个信号NaN,但是还没有找到一种办法。 你可以写这段代码: 函数SNaN:Double; begin PInt64(@Result)^:= $ 7FF7FFFFFFFFFFFF; //这个位模式指定一个SNaN end; 但ABI的浮点返回值意味着SNaN加载到浮点寄存器,以便它可以返回。当然,这导致了一个例外,而不是打破目的。 所以,你可以这样编写代码: 程序SetToSNaN(out D:Double); begin PInt64(@D)^:= $ 7FF7FFFFFFFFFFFF; 结束 现在,这是有效的,但这是非常不方便的。假设您需要将SNaN传递给另一个功能。理想情况下,您想写: Foo(SNaN) ,而您必须这样做: var SNaN:双 .... SetToSNaN(SNaN); Foo(SNaN); 所以,建立之后,这里是问题。 有没有办法写入 x:= SNaN 并将浮点变量 x 一个值是一个信号NaN?解决方案此声明在编译时解决: const iNaN:UInt64 = $ 7FF7FFFFFFFFFFFF; var SNaN:Double absolute iNaN; 编译器仍将 SNaN 视为 尝试将值分配给 SNaN 会给出编译时错误: E2064左侧无法分配给。 程序DoSomething(var d:Double); begin d:= 2.0; 结束 SNaN:= 2.0; // DoSomething(SNaN); //< - E2197常量对象不能作为var参数 WriteLn(Math.IsNaN(SNaN))传递; //< - 写true 如果您有编译器指令 $ WRITEABLECONSTS ON (或 $ J + ),这可以暂时关闭,以确保不会更改 SNaN {$ IFOPT J +} {$ DEFINE UNDEFWRITEABLECONSTANTS} {$ J - } {$ ENDIF} const iNaN:UInt64 = $ 7FF7FFFFFFFFFFFF; var SNaN:Double ABSOLUTE iNaN; {$ IFDEF UNDEFWRITEABLECONSTANTS} {$ J +} {$ ENDIF} The IEEE754 standard defines two classes of NaN, the quiet NaN, QNaN, and the signaling NaN, SNaN. When an SNaN is loaded into a floating point register, an exception is raised by the floating point unit.QNaN is available to Delphi code through the constant named NaN that is declared in Math. The definition of that constant is:const NaN = 0.0 / 0.0;I would like to be able to use something similar to declare a constant that is a signaling NaN, but have not yet found a way to do that.Naively you might write this code:function SNaN: Double;begin PInt64(@Result)^ := $7FF7FFFFFFFFFFFF;//this bit pattern specifies an SNaNend;But the ABI for floating point return values means that the SNaN is loaded into a floating point register so that it can be returned. Naturally that leads to an exception which rather defeats the purpose.So you are then led to writing code like this:procedure SetToSNaN(out D: Double);begin PInt64(@D)^ := $7FF7FFFFFFFFFFFF;end;Now, this works, but it's very inconvenient. Suppose you need to pass an SNaN to another function. Ideally you would like to write:Foo(SNaN)but instead you have to do this:var SNaN: Double;....SetToSNaN(SNaN);Foo(SNaN);So, after the build-up, here's the question.Is there any way to write x := SNaN and have the floating point variable x assigned a value that is a signaling NaN? 解决方案 This declaration solves it at compile time:const iNaN : UInt64 = $7FF7FFFFFFFFFFFF;var SNaN : Double absolute iNaN;The compiler still treats the SNaN as a constant.Trying to assign a value to SNaN will give a compile time error: E2064 Left side cannot be assigned to. procedure DoSomething( var d : Double);begin d := 2.0;end;SNaN := 2.0; // <-- E2064 Left side cannot be assigned toDoSomething( SNaN); // <--E2197 Constant object cannot be passed as var parameterWriteLn(Math.IsNaN(SNaN)); // <-- Writes "true"Should you have the compiler directive $WRITEABLECONSTS ON (or $J+), this could be turned off temporarily to ensure not altering SNaN.{$IFOPT J+} {$DEFINE UNDEFWRITEABLECONSTANTS} {$J-}{$ENDIF}const iNaN : UInt64 = $7FF7FFFFFFFFFFFF;var SNaN : Double ABSOLUTE iNaN;{$IFDEF UNDEFWRITEABLECONSTANTS} {$J+}{$ENDIF} 这篇关于如何使信号NaN容易使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 09-15 04:27