# $DOUBLE

## Synopsis

$DOUBLE(num)

### Parameter

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 an InterSystems IRIS 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 InterSystems IRIS floating-point number (NUMERIC data type).

$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 InterSystems IRIS floating-point numbers. However, standard InterSystems IRIS floating-point numbers have a greater degree of precision. In most cases, standard InterSystems IRIS floating-point numbers are preferable.

An InterSystems IRIS numeric string literal that exceeds the min/max range supported by InterSystems IRIS 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() method of the %SYSTEM.Process class. The system-wide default behavior can be established by setting the TruncateOverflow property of the Config.Miscellaneous 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 InterSystems SQL data types DOUBLE and DOUBLE PRECISION represent IEEE floating-point numbers; the NUMERIC data type represents standard InterSystems IRIS 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 InterSystems IRIS floating-point number values may yield unexpected results and should generally be avoided. Comparisons between $DOUBLE values and standard InterSystems IRIS floating-point number values are performed exactly, without rounding.

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

### Integer Divide

With certain values, InterSystems IRIS decimal floating-point and IEEE double numbers yield a different integer divide product. For example:

WRITE !,"Divide operations:" WRITE !,"IRIS /: ",4.1/.01 // 410 WRITE !,"Double /: ",$DOUBLE(4.1)/.01 // 410 WRITE !,"Integer divide operations:" WRITE !,"IRIS \: ",4.1\.01 // 410 WRITE !,"Double \: ",$DOUBLE(4.1)\.01 // 409

### Platform Independence

Standard InterSystems IRIS decimal floating-point 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 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 InterSystems IRIS 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 InterSystems IRIS 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() method of the %SYSTEM.Process class. The system-wide default behavior can be established by setting the IEEEError property of the Config.Miscellaneous 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.

The maximum supported value for an InterSystems IRIS decimal floating-point number is 9.223372036854775807e145. The minimum supported value for an InterSystems IRIS 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, 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 Server-Side 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 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 Orientation Guide for Server-Side Programming.

### 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) or $DOUBLE(+0) is stored in a JSON structure as 0.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.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 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 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

ZZDUMP command

$DECIMAL function

$FNUMBER function

$NUMBER function

Data Types in InterSystems SQL Reference

Operators in Using ObjectScript

Numeric Computing in InterSystems Applications in Orientation Guide for Server-Side Programming