Skip to main content

$NUMBER (ObjectScript)

Validates and returns a numeric value; optionally provides rounding and range checking.

Synopsis

$NUMBER(num,format,min,max)
$NUM(num,format,min,max)

Arguments

Argument Description
num The numeric value to be validated and then converted to InterSystems IRIS canonical form. It can be a numeric or string value, a variable name, or any valid ObjectScript expression.
format Optional — Specifies which processing options to apply to num. These processing options dictate primarily how to recognize and handle numbers containing decimal points.
min Optional — The minimum acceptable numeric value.
max Optional — The maximum acceptable numeric value.

Description

The $NUMBER function converts and validates the num numeric value using the specified format. It accepts numbers supplied with a variety of punctuation formats and returns numbers in InterSystems IRIS canonical form. You can use format to test whether a number is an integer. If min or max are specified, the number must fall within that range of values.

$NUMBER can be used for American format numbers, European format numbers, and Russian/Czech format numbers.

Using $NUMBER on the $DOUBLE values INF, –INF, or NAN always returns the empty string.

Arguments

format

The possible format codes are as follows. These format codes may be specified in any order. A nonnumeric format must be specified as a quoted string. Any or all of the following format codes may be omitted. If format is invalid, $NUMBER generates a <SYNTAX> error.

  • Decimal character: either “.” or “,” indicating whether to use the American (“.”) or European (“,”) convention for validating the decimal point. You can specify either of these characters, or no decimal character. If you omit the decimal character, the number takes the DecimalSeparator of the current locale. Refer to European and American Decimal Separators below.

  • Rounding factor: an integer indicating how many digits to round to. This integer can be preceded by an optional + or - sign. If the rounding factor is positive (or unsigned) the number is rounded to the specified number of fractional digits. If the rounding factor is 0, the number is rounded to an integer. If the rounding factor is a negative integer, the number is rounded the indicated number of places to the left of the decimal separator. For example, a rounding factor of -2 rounds 234.45 to 200. The number “5” is always rounded up; thus a rounding factor of 1 rounds 123.45 to 123.5. After rounding, trailing zeros are removed; thus rounding 4.0043 to two fractional digits returns 4, not 4.00. For rounding of IEEE floating point numbers refer to $DOUBLE Numbers below.

  • Integer indicator: the letter “I” (uppercase or lowercase) which specifies that the number must resolve to an integer. For example, –07.00 resolves to an integer, but –07.01 does not. If the number does not resolve to an integer, $NUMBER returns the null string. In the following example, only the first three $NUMBER functions returns an integer. The other three return the null string:

      WRITE $NUMBER(-07.00,"I"),"  non-canonical integer numeric",!
      WRITE $NUMBER(+"-07.00","I")," string forced as integer numeric",!
      WRITE $NUMBER("-7","I")," canonical integer string numeric",!
      WRITE $NUMBER("-07.00","I")," non-canonical integer string numeric",!
      WRITE $NUMBER(-07.01,"I")," fractional numeric",!
      WRITE $NUMBER("-07.01","I")," fractional string numeric",!
    

min and max

You can specify a minimum allowed value, a maximum allowed value, neither, or both. If specified, the num value (after rounding) must be greater than or equal to the min value, and less than or equal to the max value. A null string as a min or max value is equal to zero. If a value does not meet these criteria, $NUMBER returns the null string.

Thus in the following examples, the first is valid because num (4.0) equals max (4). The second is valid because num (4.003) still equals max (4) within the format range (two fractional digits). However, the third is not valid because $NUMBER rounds num up to a value (4.01) greater than max within the format range. It returns a null string.

   WRITE !,$NUMBER(4.0,2,0,4)
   WRITE !,$NUMBER(4.003,2,0,4)
   WRITE !,$NUMBER(4.006,2,0,4)  

You can omit arguments, retaining the commas as place holders. The first line of the following example sets a max value, but no format or min value. The second line sets no format value, but sets a min value of the null string, which is equivalent to zero. Thus the first line returns –7, and the second line fails the min criteria and returns the null string.

   SET max=10
   WRITE !,$NUMBER(-7,,,max)
   WRITE !,$NUMBER(-7,,"",max)

You cannot specify trailing commas. The following results in a <SYNTAX> error:

   WRITE $NUMBER(mynum,,min,)

Order of Operations

$NUMBER performs the following series of conversions and validations. If the number fails any validation step, $NUMBER returns a null string (""). If the number passes all validation steps, $NUMBER returns the resulting converted InterSystems IRIS canonical form number.

  1. $NUMBER uses the decimal character format to determine which character is the group separator and strips out all group separator characters (regardless of their location in the number). It uses the following rule: If the decimal character specified in format is a period (.), then the group separator is a comma (,) or blank space. If the decimal character specified in format is a comma (,), then the group separator is a period (.) or blank space. If no decimal character is specified in format, the group separator is the NumericGroupSeparator property of the current locale. (The Russian (rusw), Ukrainian (ukrw), and Czech (csyw) locales use a blank space as the numeric group separator.)

  2. $NUMBER validates that the number is well-formed. A well-formed number can contain any of the following:

    • Numbers

    • An optional decimal indicator character, as defined above (one or none, but not more than one).

    • An optional plus (+) or minus (-) sign character (leading or trailing, but not more than one).

    • Optional parentheses enclosing the number to indicate a negative value (debit). The number within the parentheses cannot have a sign character.

    • An optional base-10 exponent, indicated by an “E” (uppercase or lowercase) followed by an integer. If “E” is specified, an exponent integer must be present. The exponent integer may be preceded by a sign character.

  3. If the integer indicator is present in format, $NUMBER checks for integers. An integer cannot contain a decimal indicator character. Numeric strings (“123.45”) and numbers (123.45) are parsed differently. Numeric strings fail this integer test even if there are no digits following the decimal indicator character, or if expansion of scientific notation or rounding would eliminate the fractional digits. Numbers pass these validation tests. If a number fails the integer indicator check, $NUMBER returns the null string ("").

  4. $NUMBER converts the number to an InterSystems IRIS canonical form number. It expands scientific notation, replaces enclosing parentheses with a negative sign character, strips off leading and trailing zeros, and deletes a decimal indicator character if it is not followed by any nonzero digits. For scientific notation the uppercase “E” is the standard exponent operator; the lowercase “e” is a configurable exponent operator, using the %SYSTEM.Process.ScientificNotation()Opens in a new tab method.

  5. $NUMBER uses the rounding factor (if present) to round the number the specified number of digits. It then strips off any leading or trailing zeros and the decimal indicator character if it is not followed by any digits.

  6. $NUMBER validates the number against the minimum value, if specified.

  7. $NUMBER validates the number against the maximum value, if specified.

  8. $NUMBER returns the resulting number.

European and American Decimal Separators

$NUMBER returns a number in canonical form, removing all numeric group separators and includes at most one decimal separator character. You can use the format values “,” or “.” to identify the decimal separator used in num; by specifying the decimal separator, you are also implicitly specifying the numeric group separator.

To determine the DecimalSeparator character for your locale, invoke the following method:

  WRITE ##class(%SYS.NLS.Format).GetFormatItem("DecimalSeparator")

To determine the NumericGroupSeparator character and NumericGroupSize number for your locale, invoke the following methods:

  WRITE ##class(%SYS.NLS.Format).GetFormatItem("NumericGroupSeparator"),!
  WRITE ##class(%SYS.NLS.Format).GetFormatItem("NumericGroupSize")

In following examples, a comma is specified as the decimal separator:

  SET num="123,456"
  WRITE !,$NUMBER(num,",")  
     // converts to the fractional number "123.456"
     // (comma is identified as decimal separator)
  SET num="123,45,6"
  WRITE !,$NUMBER(num,",")  
    // returns the null string 
    // (invalid number, too many decimal separators)
  SET num="123.456"
  WRITE !,$NUMBER(num,",")
    // converts to the integer "123456"
    // removing group separator 
    // (if comma is decimal, then period is group separator)
  SET num="123.4.56"
  WRITE !,$NUMBER(num,",")  
    // converts to the integer "123456"
    // removing group separators 
    // (number and placement of group separators ignored)

$DOUBLE Numbers

$DOUBLE IEEE floating point numbers are encoded using binary notation. Most decimal fractions cannot be exactly represented in this binary notation. When a $DOUBLE value is input to $NUMBER with a rounding factor, the return value frequently contains more fractional digits than specified in the rounding factor. This is because the fractional decimal result is not representable in binary, so the return value must be rounded to the nearest representable $DOUBLE value, as shown in the following example:

  SET x=1234.5678
  SET y=$DOUBLE(1234.5678)
  WRITE "Decimal: ",x," rounded ",$NUMBER(x,2),!
  WRITE "Double: ",y," rounded ",$NUMBER(y,2)

When using $DOUBLE numbers, be aware that IEEE floating point numbers and standard InterSystems IRIS fractional numbers differ in precision. $DOUBLE IEEE floating point numbers are encoded using binary notation. They have a precision of 53 binary bits, which corresponds to 15.95 decimal digits of precision. (Note that the binary representation does not correspond exactly to a decimal fraction.) Because most decimal fractions cannot be exactly represented in this binary notation, an IEEE floating point number may differ slightly from the corresponding standard InterSystems IRIS floating point number. Standard InterSystems IRIS fractional numbers have a precision of 18 decimal digits on all supported InterSystems IRIS system platforms. When an IEEE floating point number is displayed as a fractional number, the binary bits are often converted to a fractional number with far more than 18 decimal digits. This does not mean that IEEE floating point numbers are more precise than standard InterSystems IRIS fractional numbers.

If you are using $NUMBER to round a $DOUBLE value and wish to return a specific number of fractional digits, you should convert the $DOUBLE value to decimal representation before rounding the result. For example:

USER>set mydouble=$double(33/100)
 
USER>write mydouble
.33000000000000001554
USER>w $number(mydouble,2)
.33000000000000001554
USER>set mydecimal=$decimal(mydouble)
 
USER>write $number(mydecimal,2)
.33

$NUMBER returns $DOUBLE("INF") or $DOUBLE("NAN") as the empty string.

See Also

FeedbackOpens in a new tab