ObjectScript Reference
$DOUBLE


Returns a number converted to a 64bit floatingpoint value.
Synopsis
$DOUBLE returns a number converted to the IEEE doubleprecision (64bit) binary floatingpoint data type. This type of floatingpoint number can contain up to 20 digits. If
num has more than 20 digits,
$DOUBLE rounds the fractional portion to the appropriate number of digits. If the integer portion of
num is more than 20 digits,
$DOUBLE rounds the integer to 20 significant digits and represents the additional digits with zeros.
$DOUBLE converts an InterSystems IRIS floatingpoint number to an IEEE doubleprecision floatingpoint number.
$DECIMAL performs the inverse operation, converting an IEEE doubleprecision floatingpoint number to a standard InterSystems IRIS floatingpoint number.
$DOUBLE generates floatingpoint numeric values that accord with the IEEE doubleprecision (64bit) binary floating point standard. It is primarily intended for interchange and compatibility with applications that use this data type standard. IEEE floatingpoint numbers are represented using binary notation. They have a precision of 53 binary bits, which corresponds to 15.95 decimal digits. (Note that the binary representation does not correspond exactly to a decimal fraction.)
IEEE floatingpoint numbers have greater min/max value range than standard InterSystems IRIS floatingpoint numbers. However, standard InterSystems IRIS floatingpoint numbers have a greater degree of precision. In most cases, standard InterSystems IRIS floatingpoint numbers are preferable.
Note:
An InterSystems IRIS numeric string literal that exceeds the min/max range supported by InterSystems IRIS floatingpoint data types (for example, “1E128”) is automatically converted to an IEEE doubleprecision floatingpoint number. This conversion is only performed on numeric literals; it is
not performed on the results of mathematical operations. This automatic conversion can be controlled on a perprocess basis using the
TruncateOverflow() method of the
%SYSTEM.Process class. The systemwide default behavior can be established by setting the
TruncateOverflow property of the
Config.Miscellaneous class.
Because numbers generated by
$DOUBLE are converted to a binary representation that does not correspond exactly to decimal digits, equality comparisons between
$DOUBLE values and standard InterSystems IRIS floatingpoint number values may yield unexpected results and should generally be avoided. Comparisons between
$DOUBLE values and standard InterSystems IRIS floatingpoint number values are performed exactly, without rounding. Arithmetic operations involving a
$DOUBLE value and a standard InterSystems IRIS number return a
$DOUBLE value. InterSystems IRIS handles conversions to/from
$DOUBLE numeric representations and comparisons between numeric representations; these operations are, therefore, the same on all platforms. However, arithmetic operations involving
$DOUBLE values are governed by the underlying operating system, and thus may occasionally differ between platforms. For further details on arithmetic operations involving IEEE double numbers, see the appendix
“Numeric Computing in InterSystems Applications” in the
Orientation Guide for ServerSide Programming.
The
num value can be specified as a number or a numeric string. It is resolved to canonical form (leading and trailing zeros removed, multiple plus and minus signs resolved, etc.) before
$DOUBLE conversion. Specifying a nonnumeric string to
num returns 0. Specifying a mixednumeric string (for example "7dwarves" or "7.5.4") to
num truncates the input value at the first nonnumeric character then converts the numeric portion.
The InterSystems SQL data types DOUBLE and DOUBLE PRECISION represent IEEE floatingpoint numbers; the FLOAT data type represents standard InterSystems IRIS floatingpoint numbers.
With certain values, InterSystems IRIS decimal floatingpoint and IEEE double numbers yield a different integer divide product. For example:
WRITE !,"Divide operations:"
WRITE !,"Cache /: ",4.1/.01 // 410
WRITE !,"Double /: ",$DOUBLE(4.1)/.01 // 410
WRITE !,"Integer divide operations:"
WRITE !,"Cache \: ",4.1\.01 // 410
WRITE !,"Double \: ",$DOUBLE(4.1)\.01 // 409
Standard InterSystems IRIS decimal floatingpoint numbers (
$DECIMAL numbers) have an approximate precision of 18.96 decimal digits. This precision is consistent across all system platforms that InterSystems IRIS supports.
IEEE doubleprecision floatingpoint numbers (
$DOUBLE numbers) have a standard internal representation that is platformindependent. Conversions and comparisons between
$DOUBLE and
$DECIMAL numbers are consistent across all system platforms that InterSystems IRIS supports. However, other computations on
$DOUBLE numbers may show slight differences based on the system platform.
Following the IEEE standard,
$DOUBLE can return the strings INF (infinity) and NAN (not a number). INF can be positive or negative (INF and INF); NAN is always unsigned. While these are valid IEEE return values, they are not actual numbers.
INF and NAN as Input Values
One way to cause
$DOUBLE to return INF and NAN is to specify the corresponding string as the
num input value. These input strings are not casesensitive, and can take leading plus and minus signs (INF resolves signs, NAN ignores signs). To return NAN, specify “NAN”, “sNAN”, “+NAN”, “NAN”. To return INF, specify “INF”, “+INF”, “Infinity”. To return INF, specify “INF”, “+INF”.
IEEEError controls how
$DOUBLE responds to a numeric conversion that cannot be resolved. If IEEEError is set to 0,
$DOUBLE returns INF and NAN when it cannot resolve a conversion. If IEEEError is set to 1,
$DOUBLE generates standard InterSystems IRIS error codes when it cannot resolve a conversion. The default is 1.
$DOUBLE can return INF and NAN when you specify an extremely large number, or when you specify an unresolvable arithmetic operation. These values are only returned when IEEEError is set to return INF and NAN.
Extremely large floatingpoint numbers are not supported. The maximum supported value for a
$DOUBLE binary floatingpoint number is 1.7976931348623158079e308. The minimum supported value for a
$DOUBLE binary floatingpoint number is 1.0E323. A
num value smaller than this returns 0.
Note:
The maximum supported value for an InterSystems IRIS decimal floatingpoint number is 9.223372036854775807e145. The minimum supported value for an InterSystems IRIS decimal floatingpoint number is either 2.2250738585072013831e308 (normal) or 4.9406564584124654417e324 (denormalized).
The following table shows the value returned or error generated by unresolvable arithmetic operations:
INF can be compared as if it were a numerical value. Thus INF = INF, INF '= –INF, –INF = –INF, and INF > –INF.
NAN cannot be compared as if it were a numerical value. Because NAN (Not A Number) cannot be meaningfully compared using numerical operators, InterSystems IRIS operations (such as equal to, less than, or greater than) that attempt to compare $DOUBLE(“NAN”) to another $DOUBLE(“NAN”) fail. Comparisons with NAN <= or >= are a special case, which is described in the appendix
“Numeric Computing in InterSystems Applications” in the
Orientation Guide for ServerSide Programming.
$LISTSAME does consider a $DOUBLE(“NAN”) list element to be identical to another $DOUBLE(“NAN”) list element.
InterSystems IRIS does not distinguish between different NAN representations (NAN, sNAN, etc.). InterSystems IRIS considers all NANs to be the same, regardless of their binary representation.
$ISVALIDNUM, $INUMBER, and $FNUMBER
These ObjectScript functions provide support for
$DOUBLE numbers.
$ISVALIDNUM supports INF and NAN. Although these strings are not numbers,
$ISVALIDNUM returns 1 for these values, just as if they were numbers. When
$DOUBLE is specified with a nonnumeric string, for example
$DOUBLE(""), InterSystems IRIS returns a value of 0. For this reason,
$ISVALIDNUM($DOUBLE("")) returns 1, because 0 is a number.
$INUMBER and
$FNUMBER provide a “D” format option that supports
$DOUBLE values.
$INUMBER converts a numeric to a IEEE floatingpoint number.
$FNUMBER “D” support includes case conversion of INF and NAN, and choosing whether
$DOUBLE(0) should return 0 or 0.
INF and NAN with Operators
You can perform arithmetic and logical operations on INF and NAN. Use of operators with INF and NAN is not recommended; if such an operation is performed, the following are the results:
Other operators, such as pattern matching and concatenation, treat NAN and INF as threecharacter alphabetic strings.
$DOUBLE returns an INF value (or a INF for negative numbers) when the numeric value exceeds the available precision, as shown in the following example:
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)
$DOUBLE returns a NAN (not a number) value when the numeric value is invalid. For example, when an arithmetic expression involves two INF values, as shown in the following example. (An arithmetic expression involving a single INF value returns INF.)
SET rtn=##class(%SYSTEM.Process).IEEEError(0)
SET x=$DOUBLE(1.2e500)
WRITE !,"Double: ",x
WRITE !,"Is number? ",$ISVALIDNUM(x)
SET y= $DOUBLE(xx)
WRITE !,"Double INF minus INF: ",y
WRITE !,"Is number? ",$ISVALIDNUM(y)
The following example returns floatingpoint numbers of 20 digits:
WRITE !,$DOUBLE(999.12345678987654321)
WRITE !,$DOUBLE(.99912345678987654321)
WRITE !,$DOUBLE(999123456789.87654321)
The following example returns the value of pi as a $DOUBLE value and as a standard InterSystems IRIS numeric value. This example shows that equality operations should not be attempted between
$DOUBLE and standard InterSystems IRIS numbers, and that the number of digits returned is greater for standard InterSystems IRIS numbers:
SET x=$ZPI
SET y=$DOUBLE($ZPI)
IF x=y { WRITE !,"Same" }
ELSE { WRITE !,"Different"
WRITE !,"standard: ",x
WRITE !,"IEEE float: ",y }
The following examples show that a floatingpoint number is not necessarily equivalent to a numeric string of the same value:
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" }
SET x=1234567891234560
SET y=1234567891234567
IF x=$DOUBLE(x) { WRITE !,"Same" }
ELSE { WRITE !,"Different" }
IF y=$DOUBLE(y) { WRITE !,"Same" }
ELSE { WRITE !,"Different" }