第十三章 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 <MAXNUMBER>
< 1.0E-323 0 0
1/$DOUBLE(0) INF <DIVIDE>
1/$DOUBLE(–0) –INF <DIVIDE>
$DOUBLE(1)/0 INF <DIVIDE>
$DOUBLE(0)/0 NAN <ILLEGAL VALUE>
$ZLOG($DOUBLE(0)) –INF <DIVIDE>

比较INF和NAN

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

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

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

ISVALIDENUM,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()返回。尝试这样做会导致<ILLEGAL VALUE>错误,如下例所示:
/// d ##class(PHA.TEST.Function).double2()
ClassMethod double2()
{
    SET jary=[123,($DOUBLE("INF"))]  // executes successfully
    WRITE jary.%ToJSON()            // fails with <ILLEGAL VALUE> 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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352