第十二章 Caché 函数大全 $DECIMAL 函数

164 阅读2分钟

第十二章 Caché 函数大全 $DECIMAL 函数

返回转换为Caché浮点值的数字。

大纲

$DECIMAL(num,digits)

参数

  • num 要转换的数值。通常,这是一个IEEE浮点数。
  • digits 可选—一个整数,指定要返回的有效位数。$DECIMAL使用IEEE浮点舍入算法将返回值舍入到该位数。有效值为1到38,以及0。如果digits大于位数,则该值将保持不变。如果digits为0,则对num不进行舍入,除非有效位数超过20个。

描述

$DECIMAL返回转换为Caché十进制浮点数据类型的浮点数。此函数用于将IEEE双精度(64位)二进制浮点格式的小数转换为Caché十进制浮点格式的相应小数。这与$DOUBLE函数执行的操作相反。

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

IEEE浮点数在内部使用53个二进制位表示。由于大多数小数十进制数字都没有精确的二进制表示形式,因此$DOUBLE格式的小数通常与$DECIMAL转换略有不同。在所有受支持的Caché系统平台上,标准Caché小数部分的精度约为18.96个十进制数字。当IEEE浮点数显示为小数时,二进制位通常会转换为具有远远超过18个十进制数字的小数。这并不意味着IEEE浮点数比标准Caché小数更精确。

num值可以指定为数字或数字字符串。在$DECIMAL转换之前,它将解析为规范形式(删除了前导零和尾随零,解决了多个正负号等)。如果num值超出可以转换为FLOAT数据类型的值范围,则$DECIMAL会生成<MAXNUMBER>错误。为num指定非数字字符串将返回0。为num指定混合数字字符串(例如“7dwarves”“ 7.5.4”)会截断第一个非数字字符的输入值,然后转换数字部分。

默认四舍五入如下:

  • 小数部分:如果未指定数字,并且num具有19个以上有效数字,则$DECIMAL将小数部分四舍五入,以使结果数字为19位数字(如果四舍五入后跟零,则为更少)。 $DECIMAL始终四舍五入为具有较大绝对值的最接近的小数。
  • 非常大的整数:如果未指定数字,并且num在小数点左边有超过19个有效整数,则$DECIMAL会四舍五入,以使所得整数具有19个有效数字,其余整数用零表示。
  • 小于1的非常小的分数数字:如果未指定digits,并且num是在有效值前的小数点右边的小数点右边有19个零以上的小数,$DECIMAL将保留零,然后四舍五入,以便将有效位的小数部分四舍五入。小数舍入为19位有效数字。
  • 具有非常小的分数数字的整数:如果未指定数字,并且num是一个数字,则该数字包含一个非零整数部分,在有效值前小数点右边有19个零以上,$DECIMAL会四舍五入为整数。

digits参数可用于将返回值四舍五入到指定的位数。尾随零始终被删除。如果数字是一个正整数,则使用IEEE舍入标准进行舍入。如果num具有38个以上的有效数字(且数字=38),则$DECIMAL将数字的小数部分四舍五入到第38个数字,并用零表示接下来的所有num数字。如果数字大于38,则会生成<ILLEGAL VALUE>错误。

如果digits为0,则数字强制转换为字符串排序规则;否则为0。相当于(+ num)_“”。如果num为20位以下,则digits = 0与digits = 20相同。

但是,如果数字为0且num大于20个数字,则执行特殊舍入(不是IEEE舍入),如下所示。进行四舍五入以返回20位数字。如果第20位四舍五入为0或5,则对第20位进行特殊舍入。如果第20位四舍五入为0或5,则Caché分别将其舍入为9或4。如果第20位数字向下舍入为0或5,则Caché分别将其向上舍入为1或6。其他20位数字值则保持不变。该舍入算法用于提供正确的数字排序规则,并避免舍入不一致。

整数除法

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

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

INF 与 NAN

如果num是INF,则会生成<MAXNUMBER>错误。如果num是NAN,则会生成 <ILLEGAL VALUE> 错误。这些无效值显示在以下示例中:

DHC-APP>SET i=$DOUBLE("INF")
 
DHC-APP>SET n=$DOUBLE("NAN")
 
DHC-APP>WRITE $DECIMAL(i)
 
WRITE $DECIMAL(i)
^
<MAXNUMBER>
DHC-APP>WRITE $DECIMAL(n)
 
WRITE $DECIMAL(n)
^
<ILLEGAL VALUE>

示例

以下示例说明,将$DECIMAL应用于已经采用Caché格式的小数时无效:

/// d ##class(PHA.TEST.Function).decimal()
ClassMethod decimal()
{
	SET x=$DECIMAL($ZPI)
	SET y=$ZPI
	IF x=y { 
		WRITE !,"相同:"
		WRITE !,"Cache $DECIMAL: ",x
		WRITE !,"Native Cache:   ",y 
	} ELSE { 
		WRITE !,"不同:"
		WRITE !,"Cache $DECIMAL: ",x
		WRITE !,"Native Cache:   ",y 
	}
}

以下示例将pi的值作为$DOUBLE值和标准Caché数值返回。此示例表明,不应在$DOUBLE和标准Caché编号之间尝试相等操作,并且不能通过使用$DECIMAL将IEEE转换回Caché来恢复等效性:

/// d ##class(PHA.TEST.Function).decimal1()
ClassMethod decimal1()
{
	SET x=$DECIMAL($ZPI)
	SET y=$DOUBLE($ZPI)
	SET z=$DECIMAL(y)
	IF x=y { 
		WRITE !,"Cache & IEEE Same" 
	} ELSEIF x=z { 
		WRITE !,"Cache & IEEE-to-Cache same" 
	} ELSE { 
		WRITE !,"三者不同"
		WRITE !,"Cache decimal: ",x
		WRITE !,"IEEE float:    ",y
		WRITE !,"IEEE to Cache: ",z 
	}
}
DHC-APP>d ##class(PHA.TEST.Function).decimal1()
 
三者不同
Cache decimal: 3.141592653589793238
IEEE float:    3.1415926535897931159
IEEE to Cache: 3.141592653589793116

以下示例将pi的$DECIMAL转换返回为$DOUBLE值。这些转换通过不同的数字参数值取整:

/// d ##class(PHA.TEST.Function).decimal2()
ClassMethod decimal2()
{
	SET x=$DOUBLE($ZPI)
	WRITE !,$DECIMAL(x)
	/* returns 3.141592653589793116 (19 digits) */
	WRITE !,$DECIMAL(x,1)
	/* returns 3 */
	WRITE !,$DECIMAL(x,8)
	/* returns 3.1415927 (note rounding) */
	WRITE !,$DECIMAL(x,12)
	/* returns 3.14159265359 (note rounding) */
	WRITE !,$DECIMAL(x,18)
	/* returns 3.14159265358979312 */
	WRITE !,$DECIMAL(x,19)
	/* returns 3.141592653589793116 (19 digits) */
	WRITE !,$DECIMAL(x,20)
	/* returns 3.141592653589793116 (19 digits) */
	WRITE !,$DECIMAL(x,21)
	/* returns 3.141592653589793116 (19 digits) */
	WRITE !,$DECIMAL(x,0)
	/* returns 3.1415926535897931159 (20 digits) */
}

DHC-APP>d ##class(PHA.TEST.Function).decimal2()
 
3.141592653589793116
3
3.1415927
3.14159265359
3.14159265358979312
3.141592653589793116
3.141592653589793116
3.141592653589793116
3.1415926535897931159