2.4.12 The NUMERIC Instruction
     NUMERIC = DIGITS [ expr ] ;
          FORM [ SCIENTIFIC | ENGINEERING | [ VALUE ] expr ] ;
          FUZZ [ expr ] ;

REXX has an unusual form of arithmetic.  Most programming
languages use integer and floating point arithmetic, where numbers
are coded as bits in the computers native memory words. However,
REXX uses floating point arithmetic of arbitrary precision, that
operates on strings representing the numbers. Although much
slower, this approach gives lots of interesting functionality.
Unless number-crunching is your task, the extra time spent by the
interpreter is generally quite acceptable and often almost
unnoticeable.

The NUMERIC statement is used to control most aspects of
arithmetic operations. It has three distinct forms: DIGITS, FORM
and FUZZ; which to choose is given by the second token in the
instruction:

DIGITS
     Is used to set the number of significant digits in arithmetic
     operations. The initial value is 9, which is also the default
     value if expr is not specified. Large values for DIGITS tend
     to slow down some arithmetic operations considerably. If
     specified, expr must be a positive integer.

FUZZ
     Is used in numeric comparisons, and its initial and default
     value is 0. Normally, two numbers must have identical numeric
     values for a number of their most significant digits in order
     to be considered equal. How many digit are considered is
     determined by DIGITS. If DIGITS is 4, then 12345 and 12346
     are equal, but not 12345 and 12356.  However, when FUZZ is
     non-zero, then only the DIGITS minus FUZZ most significant
     digits are checked. E.g. if DIGITS is 4 and FUZZ are 2, then
     1234 and 1245 are equal, but not 1234 and 1345.

     The value for FUZZ must be a non-negative integer, and less
     than the value of DIGITS. FUZZ is seldom used, but is useful
     when you want to make comparisons less influenced by
     inaccuracies.  Note that using with values of FUZZ that is
     close to DIGITS may give highly surprising results.

FORM
     Is used to set the form in which exponential numbers are
     written.  It can be set to either SCIENTIFIC or ENGINEERING.
     The former uses a mantissa in the range 1.000... to 9.999...,
     and an exponent which can be any integer; while the latter
     uses a mantissa in the range 1.000... to 999.999..., and an
     exponent which is dividable by 3. The initial and default
     setting is SCIENTIFIC. Following the subkeyword FORM may be
     the subkeywords SCIENTIFIC and ENGINEERING, or the subkeyword
     VALUE. In the latter case, the rest of the statement is
     considered an expression, which will evaluate to either
     SCIENTIFIC or ENGINEERING.  However, if the first token of
     the expression following VALUE is neither a symbol nor
     literal string, then the VALUE subkeyword can be omitted.

The setting of FORM never affects the decision about whether to
choose exponential form or normal floating point form; it only
affects the appearance of the exponential form once that form has
been selected.

Many things can be said about the usefulness of FUZZ. My
impression is that it is seldom used in REXX programs. One problem
is that it only addresses relative inaccuracy: i.e. that the
smaller value must be within a certain range, that is determined
by a percentage of the larger value. Often one needs absolute
inaccuracy, e.g. two measurements are equal if their difference
are less than a certain absolute threshold.

Example: Simulating relative accuracy with absolute accuracy

As explained above, REXX arithmetic has only relative accuracy, in
order to obtain absolute accuracy, one can use the following
trick:

     numeric fuzz 3
     if a=b then
          say ‘relative accuracy’
     if abs(a-b)<=500 then
          say ‘absolute accuracy’

In the first IF instruction, if A is 100,000, then the range of
values for B which makes the expression true is 99,500—100,499,
i.e. an inaccuracy of about +-500. If A has the value 10,000,000,
then B must be within the range 9,950,000—10,049,999; i.e. an
inaccuracy of about +-50,000.

However, in the second IF instruction, assuming A is 100,000, the
expression becomes true for values of B in the range
99,500—100,500. Assuming that A is 10,000,000, the expression
becomes true for values of B in the range 9,999,500—10,000,500.

The effect is largely to force an absolute accuracy for the second
example, no matter what the values of A and B are. This
transformation has taken place since an arithmetic subtraction is
not affected by the NUMERIC FUZZ, only numeric comparison
operations. Thus, the effect of NUMERIC FUZZ on the implicit
subtraction in the operation = in the first IF has been removed by
making the subtraction explicit.

Note that there are some minor differences in how numbers are
rounded, but this can be fixed by transforming the expression into
something more complex.

To retrieve the values set for NUMERIC, you can use the built-in
functions DIGITS(), FORM(), and FUZZ(). These values are saved
across subroutine calls and restored upon return.



PREV NEXT