第十三章 Caché 函数大全 $DOUBLE 函数

第十三章 Caché 函数大全 $DOUBLE 函数

返回转换为64位浮点值的数字。

大纲

$DOUBLE(num)

参数

  • num 要转换的数值。还可以指定字符串“NAN”和“INF”(及其变体)。

描述

$DOUBLE返回一个转换为IEEE双精度(64位)浮点数据类型的数字。这种类型的浮点数最多可以包含20位数字。转换为IEEE双精度(64位)浮点数据类型。如果num的位数超过20位,则$DOUBLE将小数部分四舍五入为合适的位数。如果num的整数部分大于20个数字,则$DOUBLE将整数四舍五入为20个有效数字,并用零表示其他数字。

$DOUBLE将Caché浮点数转换为IEEE双精度浮点数。 $DECIMAL执行逆运算,将IEEE双精度浮点数转换为标准Caché浮点数。

$DOUBLE生成符合IEEE双精度(64位)二进制浮点标准的浮点数值。它主要用于与使用此数据类型标准的应用程序互换和兼容。 IEEE浮点数使用二进制表示法表示。它们具有53个二进制位的精度,对应于15.95个十进制数字。 (请注意,二进制表示形式并不完全对应于小数部分。)

与标准Caché浮点数相比,IEEE浮点数的最小/最大值范围更大。但是,标准的Caché浮点数具有更高的精度。在大多数情况下,最好使用标准Caché浮点数。

注意:超出Caché浮点数据类型(例如“1E128”)支持的最小/最大范围的Caché数字字符串文字将自动转换为IEEE双精度浮点数。此转换仅在数字文字上执行;它不是对数学运算的结果执行的。可以使用%SYSTEM.Process类的TruncateOverflow()方法在每个进程的基础上控制此自动转换。可以通过设置Config.Miscellaneous类的TruncateOverflow属性来建立系统范围的默认行为。

num值可以指定为数字或数字字符串。解析为规范形式(删除了前导零和尾随零,解析了多个正负号,等等)。在$DOUBLE转换之前。为num指定非数字字符串将返回0。为num指定混合数字字符串(例如“7dwarves”或“7.5.4”)会截断第一个非数字字符的输入值,然后转换数字部分。提供给JSON数组或JSON对象的$DOUBLE数值遵循不同的验证和转换规则。

CachéSQL数据类型DOUBLE和DOUBLE PRECISION表示IEEE浮点数; FLOAT数据类型表示标准的Caché浮点数。

均等比较和混合算法

由于$DOUBLE生成的数字将转换为与十进制数字不完全对应的二进制表示形式,因此$DOUBLE值与标准Caché浮点数值之间的相等比较可能会产生意外结果,通常应避免这样做。$DOUBLE值和标准Caché浮点数值之间的比较可以精确地执行,而无需四舍五入。

包含$DOUBLE值和一个或多个标准Caché编号的混合算术运算将返回$DOUBLE值。在混合算术中,Caché在执行算术运算之前会自动将所有数字转换为$DOUBLE值。 Caché处理与$DOUBLE数字表示之间的转换以及数字表示之间的比较;因此,这些操作在所有平台上都是相同的。但是,涉及$DOUBLE值的算术运算由基础操作系统控制,因此有时在平台之间可能有所不同。

整数除法

对于某些值,Caché十进制浮点数和IEEE双精度数会产生不同的整数除积。例如:

DHC-APP> WRITE !,"Cache  /: ",4.1/.01           // 410
 
Cache  /: 410
DHC-APP>WRITE !,"Double /: ",$DOUBLE(4.1)/.01  // 410
 
Double /: 409.99999999999994316
DHC-APP>WRITE !,"Cache  \: ",4.1\.01           // 410
 
Cache  \: 410
DHC-APP>WRITE !,"Double \: ",$DOUBLE(4.1)\.01  // 409
 
Double \: 409

平台独立性

标准Caché十进制浮点数($DECIMAL数字)的精度约为18.96十进制数字。 Caché支持的所有系统平台的精度都是一致的。

IEEE双精度浮点数($DOUBLE数)具有独立于平台的标准内部表示形式。

在Caché支持的所有系统平台上,$DOUBLE$DECIMAL号之间的转换和比较是一致的。但是,基于系统平台,对$DOUBLE编号的其他计算可能会显示细微的差异。

INF 与 NAN

按照IEEE标准,$DOUBLE可以返回字符串INF(无穷大)和NaN(不是数字)。Inf可以是正的或负的(INF-INF);NaN始终是无符号的。虽然这些是有效的IEEE返回值,但它们不是实际数字。

INF和NAN作为输入值

导致$DOUBLE返回INFNAN的一种方法是将相应的字符串指定为num输入值。这些输入字符串不区分大小写,并且可以带正负号(INF解析符号,NAN忽略符号)。要返回NAN,请指定“NAN”,“ sNAN”,“ + NAN”,“-NAN”。要返回INF,请指定“ INF”,“ + INF”,“ Infinity”。要返回-INF,请指定“ -INF”,“ +-INF”

IEEEError

IEEEError控制$DOUBLE如何响应无法解析的数字转换。如果IEEEError设置为0,则$DOUBLE无法解析转换时将返回INFNAN。如果IEEEError设置为1,则$DOUBLE在无法解析转换时会生成标准的Caché错误代码。预设值为1。

可以使用%SYSTEM.Process类的IEEEError()方法在每个进程的基础上控制此行为。可以通过设置Config.Miscellaneous类的IEEEError属性来建立系统范围的默认行为。

返回 INF 与 NAN

当指定一个非常大的数字或指定一个不可解析的算术运算时,$DOUBLE可以返回INFNAN。仅当将IEEEError设置为返回INFNAN时,才返回这些值。

不支持极大的浮点数。DOUBLE二进制浮点数的最大支持值为1.7976931348623158079e308$DOUBLE二进制浮点数的最小支持值为1.0E-323。小于此数值的num返回0。

注意:Caché十进制浮点数的最大支持值为9.223372036854775807e145。 Caché十进制浮点数的最小支持值为2.2250738585072013831e-308(常规)或4.9406564584124654654417e-324(非规范化)。

下表显示了不可解析的算术运算返回的值或产生的错误:

输入值 IEEEError=0 IEEEError=1
> 1.0E308 INF
< 1.0E-323 0 0
1/$DOUBLE(0) INF
1/$DOUBLE(–0) –INF
$DOUBLE(1)/0 INF
$DOUBLE(0)/0 NAN
$ZLOG($DOUBLE(0)) –INF

比较INF和NAN

可以将INF视为数值进行比较。因此,INF = INFINF'= –INF–INF = –INF,并且INF> –INF

不能将NAN视为数值进行比较。因为不能使用数值运算符来有意义地比较NAN(非数字),所以Caché运算(例如,等于,小于或大于)试图将$DOUBLE(“NAN”)与另一个$DOUBLE(“NAN”)进行比较。失败。与NAN <=> =的比较是一种特殊情况。

$LISTSAME确实认为$DOUBLE(“NAN”)列表元素与另一个$DOUBLE(“NAN”)列表元素相同。

NUMBER和$FNUMBER

这些ObjectScript函数支持$DOUBLE数字。

$ISVALIDNUM支持INFNAN。尽管这些字符串不是数字,但是$ISVALIDNUM对于这些值返回1,就像它们是数字一样。当用非数字字符串指定$DOUBLE时,例如$DOUBLE(“”),Caché返回值0。因此,$ISVALIDNUM($DOUBLE(“”)))返回1,因为0是一个数字。

$INUMBER$FNUMBER提供支持$DOUBLE值的“D”格式选项。$INUMBER将数字转换为IEEE浮点数。$FNUMBER“D”支持包括INFNAN的大小写转换,以及选择$DOUBLE(-0)应该返回0还是-0。

INF和NAN与操作符

可以对INFNAN执行算术和逻辑运算。不建议将操作符与INFNAN一起使用;如果执行了这样的操作,则结果如下:

算术运算符:

加法 减法 乘法 除法(/\#运算符)
NAN+NAN=NAN NAN-NAN=NAN NAN*NAN=NAN NAN/NAN=NAN
NAN+INF=NAN NAN-INF=NAN NAN*INF=NAN NAN/INF=NAN
INF-NAN=NAN INF/NAN=NAN
INF+INF=INF INF-INF=NAN INF*INF=INF INF/INF=NAN

逻辑运算符:

等于(= NAN INF
NAN 0 0
INF 0 1
小于 (<) 或大于 (>) NAN INF
NAN 0 0
INF 0 0

其他运算符(如模式匹配和串联)将NaNINF视为三个字符的字母字符串。

INF and NAN 示例

$DOUBLE在数值超出可用精度时返回INF值(如果是负数,则返回-INF),如下例所示:

/// d ##class(PHA.TEST.Function).double()
ClassMethod double()
{
    SET rtn=##class(%SYSTEM.Process).IEEEError(0)
    SET x=$DOUBLE(1.2e300)
    WRITE !,"Double: ",x
    WRITE !,"Is number? ",$ISVALIDNUM(x)
    SET y= $DOUBLE(x*x)
    WRITE !,"Double squared: ",y
    WRITE !,"Is number? ",$ISVALIDNUM(y)
}

DHC-APP>d ##class(PHA.TEST.Function).double()
 
Double: 1200000000000000063100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Is number? 1
Double squared: INF
Is number? 1

$DOUBLE在数值无效时返回NaN(非数字)值。例如,当算术表达式涉及两个INF值时,如下例所示。(涉及单个INF值的算术表达式返回INF。)

/// d ##class(PHA.TEST.Function).double1()
ClassMethod double1()
{
    SET rtn=##class(%SYSTEM.Process).IEEEError(0)
    SET x=$DOUBLE(1.2e500)
    WRITE !,"Double: ",x
    WRITE !,"Is number? ",$ISVALIDNUM(x)
    SET y= $DOUBLE(x-x)
    WRITE !,"Double INF minus INF: ",y
    WRITE !,"Is number? ",$ISVALIDNUM(y)
}
DHC-APP>d ##class(PHA.TEST.Function).double1()
 
Double: INF
Is number? 1
Double INF minus INF: NAN
Is number? 1

JSON数字

数字文字的JSON验证在set命令中描述。在JSON数组或JSON对象中指定的$DOUBLE数字文字受以下附加规则的约束:

  • Inf-INFNaN值可以存储在JSON结构中,但不能由%ToJSON()返回。尝试这样做会导致错误,如下例所示:
/// d ##class(PHA.TEST.Function).double2()
ClassMethod double2()
{
    SET jary=[123,($DOUBLE("INF"))]  // executes successfully
    WRITE jary.%ToJSON()            // fails with  error
}

DHC-APP>d ##class(PHA.TEST.Function).double2()
[123,INF]

$DOUBLE(-0)以-0.0的形式存储在JSON结构中。$Double(0)作为0存储在JSON结构中。下面的示例显示了这一点:

/// d ##class(PHA.TEST.Function).double3()
ClassMethod double3()
{
    SET jary=[0,-0,($DOUBLE(0)),($DOUBLE(-0))] 
    WRITE jary.%ToJSON()  // returns [0,-0,0,-0.0]
}
DHC-APP>d ##class(PHA.TEST.Function).double3()
[0,-0,0,0]

示例

下面的示例返回20位浮点数:

DHC-APP>WRITE !,$DOUBLE(999.12345678987654321)
 
999.12345678987651353
DHC-APP>WRITE !,$DOUBLE(.99912345678987654321)
 
.99912345678987657393
DHC-APP>WRITE !,$DOUBLE(999123456789.87654321)
 
999123456789.87658691

以下示例将pi的值作为$DOUBLE值和标准Caché数值返回。此示例表明,不应在$DOUBLE和标准Caché数字之间尝试相等操作,并且对于标准Caché数字,返回的位数更大:

/// d ##class(PHA.TEST.Function).double4()
ClassMethod double4()
{
    SET x=$ZPI
    SET y=$DOUBLE($ZPI)
    IF x=y { 
        WRITE !,"Same" 
    } ELSE { 
        WRITE !,"Different"
        WRITE !,"standard:   ",x
        WRITE !,"IEEE float: ",y 
    }
}
DHC-APP>d ##class(PHA.TEST.Function).double4()
 
Different
standard:   3.141592653589793238
IEEE float: 3.1415926535897931159

下面的示例说明浮点数不一定等于相同值的数字字符串:


/// d ##class(PHA.TEST.Function).double5()
ClassMethod double5()
{
    SET x=123.4567891234560
    SET y=123.4567891234567
    IF x=$DOUBLE(x) { 
        WRITE !,"Same" 
    } ELSE { 
        WRITE !,"Different" 
    }
    IF y=$DOUBLE(y) { 
        WRITE !,"Same" 
    } ELSE { 
        WRITE !,"Different" 
    }
}
DHC-APP>d ##class(PHA.TEST.Function).double5()
 
Different
Different
/// d ##class(PHA.TEST.Function).double6()
ClassMethod double6()
{
    SET x=1234567891234560
    SET y=1234567891234567
    IF x=$DOUBLE(x) { 
        WRITE !,"Same" 
    } ELSE { 
        WRITE !,"Different" 
    }
    IF y=$DOUBLE(y) { 
        WRITE !,"Same" 
    } ELSE { 
        WRITE !,"Different" 
    }
}
DHC-APP>d ##class(PHA.TEST.Function).double6()
 
Same
Same

你可能感兴趣的:(第十三章 Caché 函数大全 $DOUBLE 函数)