第十三章 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
返回INF
和NAN
的一種方法是將相應的字符串指定爲num輸入值。這些輸入字符串不區分大小寫,並且可以帶正負號(INF
解析符號,NAN
忽略符號)。要返回NAN
,請指定“NAN”,“ sNAN”,“ + NAN”,“-NAN”
。要返回INF
,請指定“ INF”,“ + INF”,“ Infinity”
。要返回-INF
,請指定“ -INF”,“ +-INF”
。
IEEEError
IEEEError控制$DOUBLE
如何響應無法解析的數字轉換。如果IEEEError設置爲0,則$DOUBLE
無法解析轉換時將返回INF
和NAN
。如果IEEEError設置爲1,則$DOUBLE
在無法解析轉換時會生成標準的Caché錯誤代碼。預設值爲1。
可以使用%SYSTEM.Process類的IEEEError()
方法在每個進程的基礎上控制此行爲。可以通過設置Config.Miscellaneous
類的IEEEError屬性來建立系統範圍的默認行爲。
返回 INF 與 NAN
當指定一個非常大的數字或指定一個不可解析的算術運算時,$DOUBLE
可以返回INF
和NAN
。僅當將IEEEError設置爲返回INF
和NAN
時,才返回這些值。
不支持極大的浮點數。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 = INF
,INF'= –INF
,–INF = –INF
,並且INF> –INF
。
不能將NAN
視爲數值進行比較。因爲不能使用數值運算符來有意義地比較NAN
(非數字),所以Caché運算(例如,等於,小於或大於)試圖將$DOUBLE(“NAN”
)與另一個$DOUBLE(“NAN”)
進行比較。失敗。與NAN <=
或> =
的比較是一種特殊情況。
$LISTSAME
確實認爲$DOUBLE(“NAN”)
列表元素與另一個$DOUBLE(“NAN”)
列表元素相同。
NUMBER和$FNUMBER
這些ObjectScript函數支持$DOUBLE
數字。
$ISVALIDNUM
支持INF
和NAN
。儘管這些字符串不是數字,但是$ISVALIDNUM
對於這些值返回1,就像它們是數字一樣。當用非數字字符串指定$DOUBLE
時,例如$DOUBLE(“”)
,Caché返回值0。因此,$ISVALIDNUM($DOUBLE(“”)))
返回1,因爲0是一個數字。
$INUMBER
和$FNUMBER
提供支持$DOUBLE
值的“D”格式選項。$INUMBER
將數字轉換爲IEEE浮點數。$FNUMBER“D”
支持包括INF
和NAN
的大小寫轉換,以及選擇$DOUBLE(-0)
應該返回0還是-0。
INF和NAN與操作符
可以對INF
和NAN
執行算術和邏輯運算。不建議將操作符與INF
和NAN
一起使用;如果執行了這樣的操作,則結果如下:
算術運算符:
加法 | 減法 | 乘法 | 除法(/ 、\ 或# 運算符) |
---|---|---|---|
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 |
其他運算符(如模式匹配和串聯)將NaN
和INF
視爲三個字符的字母字符串。
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
、-INF
和NaN
值可以存儲在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