Skip to main content

$DOUBLE

Returns a number converted to a 64-bit floating-point value.

Synopsis

$DOUBLE(num)

Parameter

Argument Description
num The numeric value to be converted. You can also specify the strings “NAN” and “INF” (and their variants).

Description

$DOUBLE returns a number converted to the IEEE double-precision (64-bit) binary floating-point data type. This type of floating-point 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 a Caché floating-point number to an IEEE double-precision floating-point number. $DECIMAL performs the inverse operation, converting an IEEE double-precision floating-point number to a standard Caché floating-point number.

$DOUBLE generates floating-point numeric values that accord with the IEEE double-precision (64-bit) binary floating point standard. It is primarily intended for interchange and compatibility with applications that use this data type standard. IEEE floating-point 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 floating-point numbers have greater min/max value range than standard Caché floating-point numbers. However, standard Caché floating-point numbers have a greater degree of precision. In most cases, standard Caché floating-point numbers are preferable.

Note:

A Caché numeric string literal that exceeds the min/max range supported by Caché floating-point data types (for example, “1E128”) is automatically converted to an IEEE double-precision floating-point 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 per-process basis using the TruncateOverflow()Opens in a new tab method of the %SYSTEM.ProcessOpens in a new tab class. The system-wide default behavior can be established by setting the TruncateOverflowOpens in a new tab property of the Config.MiscellaneousOpens in a new tab class.

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 mixed-numeric string (for example "7dwarves" or "7.5.4") to num truncates the input value at the first nonnumeric character then converts the numeric portion. A $DOUBLE numeric value supplied to a JSON array or JSON object follows different validation and conversion rules.

The Caché SQL data types DOUBLE and DOUBLE PRECISION represent IEEE floating-point numbers; the FLOAT data type represents standard Caché floating-point numbers.

Equality Comparisons and Mixed Arithmetic

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 Caché floating-point number values may yield unexpected results and should generally be avoided. Comparisons between $DOUBLE values and standard Caché floating-point number values are performed exactly, without rounding.

Mixed arithmetic operations involving a $DOUBLE value and one or more standard Caché numbers return a $DOUBLE value. In mixed arithmetic, Caché automatically converts all of the numbers to $DOUBLE values before performing the arithmetic operation. Caché 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 Caché Programming Orientation Guide.

Integer Divide

With certain values, Caché decimal floating-point 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

Platform Independence

Standard Caché decimal floating-point numbers ($DECIMAL numbers) have an approximate precision of 18.96 decimal digits. This precision is consistent across all system platforms that Caché supports.

IEEE double-precision floating-point numbers ($DOUBLE numbers) have a standard internal representation that is platform-independent. Conversions and comparisons between $DOUBLE and $DECIMAL numbers are consistent across all system platforms that Caché supports. However, other computations on $DOUBLE numbers may show slight differences based on the system platform.

INF and NAN

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 case-sensitive, 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

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 Caché error codes when it cannot resolve a conversion. The default is 1.

This behavior can be controlled on a per-process basis using the IEEEError()Opens in a new tab method of the %SYSTEM.ProcessOpens in a new tab class. The system-wide default behavior can be established by setting the IEEEErrorOpens in a new tab property of the Config.MiscellaneousOpens in a new tab class.

Returning INF and NAN

$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 floating-point numbers are not supported. The maximum supported value for a $DOUBLE binary floating-point number is 1.7976931348623158079e308. The minimum supported value for a $DOUBLE binary floating-point number is 1.0E-323. A num value smaller than this returns 0.

Note:

The maximum supported value for a Caché decimal floating-point number is 9.223372036854775807e145. The minimum supported value for a Caché decimal floating-point number is either 2.2250738585072013831e-308 (normal) or 4.9406564584124654417e-324 (denormalized).

The following table shows the value returned or error generated by unresolvable arithmetic operations:

Input Value 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>

Comparing INF and NAN

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, Caché 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 Caché Programming Orientation Guide.

$LISTSAME does consider a $DOUBLE(“NAN”) list element to be identical to another $DOUBLE(“NAN”) list element.

Caché does not distinguish between different NAN representations (NAN, sNAN, etc.). Caché 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(""), Caché 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 floating-point 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:

Arithmetic operators:

Addition Subtraction Multiplication Division (/, \, or # operators)
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

Logical operators:

Equality (=) NAN INF
NAN 0 0
INF 0 1
Less Than (<) or Greater Than (>) NAN INF
NAN 0 0
INF 0 0

Other operators, such as pattern matching and concatenation, treat NAN and INF as three-character alphabetic strings.

For further details on operations involving IEEE double numbers, see the appendix “Numeric Computing in InterSystems Applications” in the Caché Programming Orientation Guide.

INF and NAN Examples

$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(x-x)
  WRITE !,"Double INF minus INF: ",y
  WRITE !,"Is number? ",$ISVALIDNUM(y)

JSON Numeric Literals

JSON validation of numeric literals is described in the SET command. $DOUBLE numeric literals specified in a JSON array or JSON object are subject to the following additional rules:

  • INF, -INF, and NAN values can be stored in JSON structures, but cannot be returned by %ToJSON(). Attempting to do so results in an <ILLEGAL VALUE> error, as shown in the following example:

      SET jary=[123,($DOUBLE("INF"))]  // executes successfully
      WRITE jary.%ToJSON()            // fails with <ILLEGAL VALUE> error
  • $DOUBLE(-0) is stored in a JSON structure as -0.0. $DOUBLE(0) is stored in a JSON structure as 0. This is shown in the following example:

      SET jary=[0,-0,($DOUBLE(0)),($DOUBLE(-0))] 
      WRITE jary.%ToJSON()  // returns [0,-0,0,-0.0]

Examples

The following example returns floating-point 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 Caché numeric value. This example shows that equality operations should not be attempted between $DOUBLE and standard Caché numbers, and that the number of digits returned is greater for standard Caché 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 floating-point 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" }

See Also

FeedbackOpens in a new tab