The NetRexx Tutorial
- Operations on Numbers
NetRexx Tutorial - Operations on Numbers


Operations on Numbers

Introduction

In this chapter we will analyse the basic arithmetic operations that you can perform on numbers. In NetRexx numbers are usually treated as strings of characters (containing digits and, eventually, a '.' sign and/or a '-' sign). This explains the possibility of having arbitrary precision arithmetic, independent of the H/W precision of your machine.

Arithmetic Operations

NetRexx handles the four basic arithmetic operations: Addition, Subtraction, Multiplication and Division. You have also other three special operators to perform Power Operation, Integer Division, and Remainder Division. To perform an arithmetic operation, you simply need to place the appropriate operator between the two terms, and assign what will be the result to a variable. Here is an example of this operation:

 
  a = 4 + 5
 

When the Interpreter encounters such an expression, the terms on the right side are evaluated, and the variable (here 'a') will get the final result (which is, as you might suspect, '9'). The following table shows the operations that you can perform on numbers:

 

 
+          Add.
-          Subtract.
*          Multiply.
/          Divide.
%          Integer divide.
                  (i.e. divide and return the integer part)
//         Remainder.
                  (i.e. divide and return the reminder;
                   this is NOT modulo, as the result may
                   be negative)
**         Power.
 
-number    (as prefix) same as 0-number.
+number    (as prefix) same as 0+number.
 
 

Some additional examples:

 
  a = 23           /* Assignment */
  b = 1            /* Assignment */
 
  c = a + b        /* Expression */
  d = a ** c + 89  /* Expression */
 

Although I believe you may be able to imagine the result of 1+1, I would like to present some small examples of arithmetic operations. The result is shown in the right column.

 
 
1+1                  ->  2
1+9                  ->  10
 
4*7                  ->  28
2**4                 ->  16
 
(1+2)/3              ->  1
1/3                  ->  0.333333333
4/3                  ->  1.33333333
5/3                  ->  1.66666667
 
1//3                 ->  1
4//3                 ->  1
5//3                 ->  2
 
1%3                  ->  0
4%3                  ->  1
5%3                  ->  1
 
 

The three ways to divide.

A special mention should be devoted to the 'three' divide operators that are used in NetRexx. The / operator performs the regular division. This produces the same result as you would get using the division key on your pocket calculator. If the result is not an integer number, you will get the integer part, a dot and as many digits as the precision is set to (see later in this chapter for considerations about precision). The % operator performs a division and returns ONLY the integer part of the result. Note that the result in NOT rounded (contrary to what I believed at the beginning of my REXX programming). It is simply truncated. The // operator again performs a division, but it returns the remainder. As you have seen in the table, this is NOT a MODULO operation, since the result might be negative. (As you will remember from school, the MODULO is a positive integer). At the risk of being pedantic, I propose a final four examples:

 
   a =  13 / 2        a = 6.5
   a =  13 % 2        a = 6
   a =  13 // 2       a = 1
   a = -13 // 2       a = -1
 

Operator Precedence

The operator precedence (or order of evaluation) controls the order in which operations are performed. NetRexx arithmetic uses the same rules you learned in primary school. This table resumes the operator precedence:

 
Precedence  Group               Operators
----------  -----------------   ---------
 
High        UNARY               + , -
 
            POWER               **
 
            MULTIPLY & DIVIDE   * , / , // , %
 
Low         ADD & SUBTRACT      + , -
 
 

As you can imagine, operators with highest precedence are evaluated first, down to the lowest ones.

If you are in doubt.

If you happen to be in doubt about operator precedence, (I sometimes am Ñ especially when dealing with different computer languages), you can use a simple trick: use parentheses. So do not be afraid to write:

 
  value = 2 + ( 4 * 32 )
 

instead of the more terse:

 
  value = 2 + 4 * 32
 

Of course, you should not use a lot of redundant parentheses inside a loop that is iterated 100 000 times in your program. The first expression in the above example is a little more CPU consuming, but in an average program it is perfectly all right, and saves time that could be lost with bugs.

Other operations on Numbers.

There are many operations you can perform on numbers apart from the ones we have just seen. These operations are performed by NetRexx built-in functions, i.e. functions that are provided by the language itself. You call on those functions in the following way:

 
  result = argument.function()
 

as you can see from the example(s):

 
  value = -9.abs()
  say value          -> 9
 
  max   = -9.max(7)
  say max            -> 7
 

This is a table of the NetRexx built-in functions that deal with numbers.

 
 
  number.abs()
    Returns the absolute value of number;
 
  number.d2c()
    Converts the number from Decimal to Character;
 
  number.d2x()
    Converts the number from Decimal to Hexadecimal;
 
  number.format()
    Performs a rounding and format over number;
 
  number.max(number1)
    Returns the largest number from a given list;
 
  number.min(number1)
    Returns the smallest number from a given list;
 
  number.sign()
    Returns the sign of a number;
 
  number.trunc()
    Returns the integer part of a number;
 
 

I again provide some examples: the right-hand column contains the results of the operations.

 
 
-2.abs()              ->  2
2.abs()               ->  2
 
12.min(1)             ->  1
12.min()              ->  12
 
1.max(42)             ->  42
12.max()              ->  12
 
-17.sign()            ->  -1
17.sign()             ->  1
 
n = 23.34
n.trunc(0)             ->  23
n.trunc()              ->  23
n.trunc(3)             ->  23.340
n.trunc(8)             ->  23.34000000
 
125.d2x()              ->  7F
71.d2c()               ->  G
 
 

Some of these instructions require a bit of more attention, and we will look at them in the paragraphs that follow.

The format() instruction.

Use the format instruction to round and format a number. The syntax of the instruction is:

 
out = format(number,before,after)
 

where before and after refers to characters before and after the decimal point.

 

number.format(before ,    after )
              ------      -----
                |           |
        (digits before)  (digits after)
                |           |
          -------- -------------
          NNNNNNNN.NNNNNNNNNNNNN
                  |
           (decimal point)

 

Suppose that the value of n is "-3.1415". This is what we get for the format() instruction:

 
 
n.format(4,2)     ->   "  -3.14"
n.format(7,5)     ->   "     -3.14150"
n.format(2,3)     ->   "-3.142"
n.format()        ->   "-3.1415"
 
 

The xmath.random() instruction

As you would expect, the xmath.random() function returns a random number. "How random" strongly depends on the implementation of Java. In NetRexx you really get random values, while on VM/CMS you get 'pseudo-random' values. This means that, in the first case, whenever you start a program you get different values; on the contrary, in the second case, the values (although random) are always the same if you do not specify a different seed. The syntax of the instruction is, as we saw:

 
 number = xmath.random(max_value)
 

You luckily do not need to modulo the result if you need random values within a certain interval Ñ the 'max_value' parameter will do it for you. A classical application of the random number generator is when you need ( for example ) to output a cookie message. If you have 150 cookie messages, you do not want to have random numbers greater than 150. All you need to specify, in order to be sure that you do not get values greater than 150, is:

 
 ptr = xmath.random(150)
 

A random(0) will be accepted, but will generate something that is not really random (the question left to you being "why?"). This is how the xmath.random() function is implemented.

 
+----------------------------------------------------------------------+
| -- method......: random                                              |08
| -- purpose.....:                                                     |09
| --                                                                   |10
|   method random(max=Rexx) public static;                             |11
|     max = max.abs()                                                  |12
|     n = Math.random() * max                                          |13
|     n = n.trunc()                                                    |14
|     return n                                                         |15
|                                                                      |16
|   method random() public static;                                     |17
|     n = random(1000)                                                 |18
|     return n                                                         |19
|                                                                      |20
+----------------------------------------------------------------------+
                                                xmath.nrx(Method:random)
Download the complete source for the xmath.nrx library

Comparative operators.

Now that you know how to perform the basic operations on two numbers, you might also want to compare them Ñ i.e. to look at which is larger or smaller, or check if they're equal. More formally, the comparative operators are used to compare two variables (or a variable and a constant) between them. The comparative operators return:

 
 
   1  - if the result of the comparison is true
 
   0  - otherwise
 
 

NetRexx has two sets of operators: the normal comparison and the strict comparison. The strict comparison is just what its name suggests Ñ two numbers must be strictly identical in order to pass the comparison.

 
NORMAL comparative operators:
 
     =                 True if terms are equal;
     \= , ^=           Not equal;
     >                 Greater than;
     <                 Less than;
 
     >< , <>           Greater than or less than
                         (same as NOT EQUAL)
     >= , ^< , \<      Greater than or equal to,
                         not less than;
     <= , ^> , \>     Less than or equal to,
                         not greater than;
 
STRICT comparative operators:
 
     ==               True if the terms are strictly equal
                         (identical)
     \== , ^==        True if terms are strictly not
                         equal
     >>               strictly greater than;
     <<               strictly less than
     >>= , ^<< , \<<  strictly greater than or equal to,
                         strictly  not less than;
     <<= , ^<< , \>>  strictly less than or equal to,
                         strictly not greater than;
 
 
BOOLEAN operators:
 
     &                AND;
 
     |                Inclusive OR;
 
     &&               Exclusive OR;
 
     ^  , \           LOGICAL NOT
 
 

We will see how to perform comparisons in the next chapter.

Controlling the precision.

The precision is the number of significant digits used in floating point computations. Roughly speaking, it is the number of digits you are expecting to have after a '.' sign in a floating point number. This table will (I hope) clarify the idea:

 
       value                      precision
       -------------------        ---------
1/3    .333333333                 9
1/3    .333333333333333333        18
1/3    .33333                     5
 

The precision of your arithmetic computations is controlled in NetRexx by the instruction:

 
  Numeric Digits [expression]
 

In NetRexx, the default value for precision is 9. In this small program we look how the instructions dealing with precision work:

 
say 1/3                             --   0.333333333
                                    --     ---------
                                    --     9 digits
Numeric Digits 18

say 1/3                             --   0.333333333333333333
                                    --     ------------------
                                    --     18 digits
 

You might now ask: "why not always run with high precision say, of 100 significant digits?" The answer is simple: the higher the precision, the slower the program. So use higher precision only when you need it, otherwise keep to the standard one. To make this point even clearer, consider the following small program, which will allow you to measure the performance speed of your machine by changing the precision:

 
+----------------------------------------------------------------------+
| -- exercise the precision                                            |01
| parse arg prec .                                                     |02
| say 'Running at precision "'prec'".'                                 |03
| numeric digits prec                                                  |04
| t1 = timer()                                                         |05
| loop i = 1 to 1000                                                   |06
|  j = 1/i                                                             |07
|  j = j                                                               |08
| end                                                                  |09
| say t1.elapsed()                                                     |10
| exit                                                                 |11
+----------------------------------------------------------------------+
                                                             numperf.nrx
Download the source for the numperf.nrx example

To run it, just type java numperf NNN where NNN is the precision you want Ñ as in the following screen dump:

 
...................................................................
rsl3pm1 (12) java numperf 5
It took 1.001 seconds.
rsl3pm1 (13)
....................................................................
                                                     numperf example

The following table was built using my HP Vectra Pentium 133MHz machine.

 
+---------------------------------------------------+
| timing for 1000 divisions at NNN digits precision |
+---------------------------------------------------+
| NNN                      time                     |
| -----              ----------                     |
|     5              1.001  sec                     |
|     9              2.642  sec                     |
|    18              6.084  sec                     |
|    50             37.181  sec                     |
+---------------------------------------------------+
                                        numperf table

These numbers will (as you can imagine) change for different machines. As a rule of thumb, the faster the machine for INTEGER operations, the smaller will be the time for big values of NNN. I again stress the fact that the FLOATING POINT capabilities of your machine are totally irrelevant for this computation: the numbers are strings, and the floating point engine of your computer is not used by the NetRexx interpreter.

A useful program: eval.

We now look at a program that will allow you to play a little with numbers. It is called eval. The basic idea is to have a small calculator that you can use to perform Arithmetic calculations from your command line.

 
+----------------------------------------------------------------------+
| -- eval                                                              |01
| --                                                                   |02
| parse arg expr                                                       |03
| r = xstring.interpret(expr,24)                                       |04
| say r                                                                |05
| exit                                                                 |06
+----------------------------------------------------------------------+
                                                                eval.nrx
Download the source for the eval.nrx example

You invoke it simply by typing:

 
  java eval expression
 

Again, in order to give you the 'feeling', here is a dump of a sample session where I use eval.

 
....................................................................
rsl3pm1 (282) java eval 2+89
91
rsl3pm1 (283) java eval '50**3 +760 -98'
125662 = 125,662 = 1.25662E+5
....................................................................
                                                     Example of eval

Note for UNIX users: expressions such as:

 
1*2
 

are (unfortunately) interpreted by the shell. In fact, the shell will try to find, in your current directory, all the files that have filenames starting with 1 and ending with 2. As there normally are none, you will get a "No Match", and the answer will be "java: No Match", definitely NOT what you would have expected. To avoid this strange behaviour put the expression between quotes, as here:

 
'1*2'
 

or call the program without any argument. The program will then prompt you for an expression, and (now that there is no shell intervention) you can freely put in any character.

Other Mathematical functions with arbitrary precision.

 
*
* WARNING:
*   The so called SLAC arbitrary precision function package
*   will be implemented in xmath v2.000.
*
 

The other mathematical high-level functions (like sin() cos() , etc. ) are available with the usage of an external package.

In the following table we summarise all the available functions. As you notice ALL the functions have an "_" character after the function name.

Note also that ALL those functions are arbitrary precision functions and are totally platform independent (i.e. you'll get the same result for the 400th decimal digit of sin(2) on an HP, SGI, PC, etc.).

 
   e()                   - returns the value of natural base e
   pi()                  - return the value of PI

   XtoY( x , y )         - x to the yth power
   ln( x )               - log of x
   log10( x )
   logbase( x , y )      -
   sqrt( x )             - square root
   exp( x )
   fact( n )             - factorial of N

   sin( x , pr , mode )  - sine of x
   cos( x , pr , mode )  - cosine of x
   tan( x , pr , mode )  - tangent of ox
   sec( x , pr , mode )  - secant of x
   csc( x , pr , mode )  - cosecant of x
   cot( x , pr , mode )  - cotangent of x

   asin( x , pr , mode ) - arcsine of x
   acos( x , pr , mode ) - arccosine of x
   atan( x , pr , mode ) - arctangent of ox

   sinh( x , pr )        - hyperbolic sine of x
   cosh( x , pr )        - hyperbolic cosine of x
   tanh( x , pr )        - hyperbolic tangent of ox

   asinh( x , pr )       - hyperbolic arcsine of x
   acosh( x , pr )       - hyperbolic arccosine of x
   atanh( x , pr )       - hyperbolic arctangent of ox

 

NOTE: As previously stated those functions are arbitrary precision, and are NOT machine H/W dependent.

Real Examples

In order to provide some examples of the mathematical NetRexx functions, I think it better to present some 'real' algorithms that may prove to be useful even if you do not use NetRexx. These programs, although they present language features that it would be better to explore in the next chapter, are taken 'as-is' from the 'Collected Algorithms from the ACM' book. The only difference you might notice is that we have taken out all the 'GOTOs', replacing them with a more structured approach (after all, those algorithms were invented in 1962, well before even REXX was invented). What I would like to stress is the fact that NetRexx is very good for algorithm description. What might interest you are, de facto, only the functions. The rest of the program has been presented simply as an example of how to call the functions themselves.

Greatest Common Divisor (gcd).

The following code is a small example of a call to a routine that computes the gcd of two integer numbers. The format of the call is:

 
n = xmath.gcd(n1,n2)
 

 
+----------------------------------------------------------------------+
| parse arg n1 n2 .                                                    |01
| say xmath.gcd(n1,n2)                                                 |02
| exit 0                                                               |03
+----------------------------------------------------------------------+
                                                                 gcd.nrx
Download the source for the gcd.nrx example

 
+----------------------------------------------------------------------+
| -- method......: gcd                                                 |26
| -- purpose.....: find the greatest common divisor                    |27
| --                                                                   |28
|   method gcd(a=int,b=int) public static                              |29
|     if a = 0 then return b                                           |30
|     if b = 0 then return a                                           |31
|     r2 = a                                                           |32
|     r1 = b                                                           |33
|     loop forever                                                     |34
|       rr = r2/r1                                                     |35
|       g = rr.trunc()                                                 |36
|       r = r2 - r1*g                                                  |37
|       if r = 0 then return r1                                        |38
|       r2 = r1                                                        |39
|       r1 = r                                                         |40
|     end                                                              |41
|                                                                      |42
+----------------------------------------------------------------------+
                                                   xmath.nrx(Method:gcd)
Download the complete source for the xmath.nrx library

The gcd() function is a NetRexx function that (unlike the BUILT-IN functions) such as max(), min(), etc. are USER-WRITTEN.

Simultaneous Linear Equations Solution

The following piece of code shows how to call a routine (called gauss) that performs the solution of a system of linear equations with the Gauss Method.

 
+----------------------------------------------------------------------+
| -- gauss                                                             |01
| --                                                                   |02
| n = 3                                                                |03
| a = rexx[n+1,n+1]                                                    |04
| y = rexx[n+1]                                                        |05
| c = rexx[n+1]                                                        |06
|                                                                      |07
| a[1,1] = 13; a[1,2] = -8;  a[1,3] = -3; y[1] = 20                    |08
| a[2,1] = -8; a[2,2] = 10;  a[2,3] = -1; y[2] = -5                    |09
| a[3,1] = -3; a[3,2] = -1;  a[3,3] = 11; y[3] = 0                     |10
|                                                                      |11
| rc = xmath.gauss(n,a,y,c)                                            |12
| say 'RC:' rc'.'                                                      |13
|                                                                      |14
| say 'Solution:'                                                      |15
| loop i = 1 to n                                                      |16
|   say c[i].format(NULL,3)                                            |17
| end                                                                  |18
| exit                                                                 |19
+----------------------------------------------------------------------+
                                                               gauss.nrx
Download the source for the gauss.nrx example

Here is the code itself. Of course, you can grab it and put it inside your program(s).

 
+----------------------------------------------------------------------+
| -- method......: gauss                                               |43
| -- purpose.....:                                                     |44
| --                                                                   |45
|   method gauss(n=int,a=Rexx[,],y=Rexx[],c=rexx[]) public static;     |46
|     b = rexx[n+1,n+1]                                                |47
|     w = rexx[n+1]                                                    |48
|     error = 0                                                        |49
|     loop i = 1 to n                                                  |50
|       loop j = 1 to n                                                |51
|         b[i,j] = a[i,j]                                              |52
|       end                                                            |53
|       w[i] = y[i]                                                    |54
|     end                                                              |55
|     loop i = 1 to n-1                                                |56
|       big = b[i,i].abs()                                             |57
|       l = i                                                          |58
|       i1 = i+1                                                       |59
|       loop j = i1 to n                                               |60
|         ab = b[j,i].abs()                                            |61
|         if ab > big then                                             |62
|           do                                                         |63
|             big = ab                                                 |64
|             l = j                                                    |65
|           end                                                        |66
|       end                                                            |67
|       if big = 0                                                     |68
|       then error = 1                                                 |69
|       else                                                           |70
|         do                                                           |71
|           if l<>i then                                               |72
|             do                                                       |73
|               loop j=1 to n                                          |74
|                 hold = b[l,j]                                        |75
|                 b[l,j] = b[i,j]                                      |76
|                 b[i,j] = hold                                        |77
|               end                                                    |78
|               hold = w[l]                                            |79
|               w[l] = w[i]                                            |80
|               w[i] = hold                                            |81
|             end                                                      |82
|           loop j = i1 to n                                           |83
|             t = b[j,i]/b[i,i]                                        |84
|             loop k = i1 to n                                         |85
|               b[j,k] = b[j,k] - t*b[i,k]                             |86
|             end                                                      |87
|             w[j] = w[j] - t*w[i]                                     |88
|           end                                                        |89
|         end                                                          |90
|     end                                                              |91
|     if b[n,n] = 0 then error = 1                                     |92
|     else                                                             |93
|       do                                                             |94
|         c[n] = w[n]/b[n,n]                                           |95
|         i = n - 1                                                    |96
|         loop until i = 0                                             |97
|           sum = 0                                                    |98
|           loop j = i+1 to n                                          |99
|             sum = sum + b[i,j] * c[j]                                |00
|           end                                                        |01
|           c[i] = (w[i] - sum) / b[i,i]                               |02
|           i = i-1                                                    |03
|         end                                                          |04
|       end                                                            |05
|     return error                                                     |06
|                                                                      |07
+----------------------------------------------------------------------+
                                                 xmath.nrx(Method:gauss)
Download the complete source for the xmath.nrx library

Operations on HEX Numbers

In this section we will look at how to perform favourite operations on HEX quantities. A HEX number is treated by NetRexx as a string. This string is composed of numbers (0-9) and letters (A-F). Although I am sure you know what a HEX number looks like, here are some simple assignments:

 
 hex1 = 'FEA078'
 hex2 = 'CAFE'
 hex3 = '1AB052'
 

As you will have noticed, I have defined these quantities as PURE strings. This makes the conversion work that we will need to do very much easier. But now what happens if you try to sum hex1 to hex2? As NetRexx understands ONLY decimal arithmetic, the operation is going to fail. The only way out is to build a small function that performs the HEX operation. This function will perform all the conversion work for us, both in the hex to decimal part and in the decimal to hex re conversion. The routine I propose is hexop() and you call it up using the following syntax:

 
hex = hexop(hex1 operation hex2)
 

NOTE: the 'operation' must be put into quotes. Why? Because we want to avoid REXX interpreting it as an ARITHMETIC addition (remember that hex1 and hex2 are NOT hexadecimal quantities). This is the function itself and, as you can see, it is very short:

 
+----------------------------------------------------------------------+
| -- method......: hexop                                               |69
| -- purpose.....: execute an HEX operation                            |70
| --                                                                   |71
|   method hexop(in=Rexx) public static                                |72
|     parse in n1 op n2                                                |73
|     n1 = n1.x2d()                                                    |74
|     n2 = n2.x2d()                                                    |75
|     select                                                           |76
|       when op = '+' then n3 = n1 + n2                                |77
|       when op = '-' then n3 = n1 - n2                                |78
|       when op = '/' then n3 = n1 / n2                                |79
|       when op = '*' then n3 = n1 * n2                                |80
|       otherwise                                                      |81
|         do                                                           |82
|           say 'Invalid operation.'                                   |83
|           exit 1                                                     |84
|         end                                                          |85
|     end                                                              |86
|     n3 = n3.d2x()                                                    |87
|     return n3                                                        |88
|                                                                      |89
+----------------------------------------------------------------------+
                                                 xmath.nrx(Method:hexop)
Download the complete source for the xmath.nrx library

As you will note from the code (apart from the parse and the interpret instruction, which we will cover later), we do a double translationÊÑ first from HEX to DECIMAL for the two terms (x2d), and then, once we have the result, back to HEX (d2x). I do not check whether the data (and the operation) are correct or not: this is left to the calling code (or to you, if you want to enhance it). Some examples:

 
say xmath.hexop('FFFF + 1A')     -> '10019'
say xmath.hexop('FFFE / 2' )     -> '7FFF'
 

Operations on Binary Numbers

Binary numbers are composed only of '0' or '1'. Again, these numbers will be NetRexx strings. At the risk of appearing very pedantic, here are some examples of binary quantities:

 
 bin1 = '10010010'
 bin2 = '100001111000'
 

The very same considerations for HEX quantities are to be found in relation to binary numbers. Since we cannot directly perform arithmetic on them, we are forced to use a function expressly made for the purpose. This function is similar to the hexop() we just saw (in fact, in accordance with my fancy, I have expressed this in its name, calling it: binop()). The only additional complication lies in the fact that you can convert to and from binaries starting only from HEX quantities. The syntax for the function is:

 
  bin = binop(bin1 operation bin2)
 

The code is a small variation on hexop:

 
+----------------------------------------------------------------------+
| -- method......: binop                                               |05
| -- purpose.....: execute a BIN operation                             |06
| --                                                                   |07
|   method binop(in=Rexx) public static                                |08
|     parse in n1 op n2                                                |09
|     n1 = n1.b2x.x2d()                                                |10
|     n2 = n2.b2x.x2d()                                                |11
|     select                                                           |12
|       when op = '+' then n3 = n1 + n2                                |13
|       when op = '-' then n3 = n1 - n2                                |14
|       when op = '/' then n3 = n1 / n2                                |15
|       when op = '*' then n3 = n1 * n2                                |16
|       otherwise                                                      |17
|         do                                                           |18
|           say 'Invalid operation.'                                   |19
|           exit 1                                                     |20
|         end                                                          |21
|     end                                                              |22
|     n3 = n3.d2x.x2b()                                                |23
|     return n3                                                        |24
|                                                                      |25
+----------------------------------------------------------------------+
                                                 xmath.nrx(Method:binop)
Download the complete source for the xmath.nrx library

Again, no check is made to ascertain if the quantities are truly binary and the operation a valid one. Some examples:

 
  say xmath.bin_op('1010 + 10')    -> '1100'
  say xmath.bin_op('1110 / 10')    -> '0111'
 

Remark on HEX and BINARY operations

A conclusive remark: as you will have have noticed, in this last case (as in the one before that, for HEX quantities) the BINARY operations are CPU-intensive in NetRexx. To perform a single addition we do six conversions and two operations (without counting the function above). I have presented the two subroutines in order to show that 'it can be done', and in a rather easy way. However, as a rule you should remember that it is always a good idea to perform ALL the arithmetic operations in your programs as decimal operations, and perform conversions at the beginning (and end) of the program itself.

Tricks with numbers.

Put dots in long numbers.

It is usually a very difficult thing to read big numbers, if they're written as:

 
100345902
 

and it would be nice to display them in the form

 
100,345,902
 

The following xmath function will do the job.

 
+----------------------------------------------------------------------+
| -- method......: dotify                                              |90
| -- purpose.....: put dots into a numeric string                      |91
| --                                                                   |92
|   method dotify(n=Rexx) public static                                |93
|     if n.datatype('N') = 0 then return n                             |94
|     parse n a '.' b                                                  |95
|     if b <> '' then b = '.'b                                         |96
|     c = ''                                                           |97
|     loop for ((a.length() - 1) % 3)                                  |98
|       c3 = a.right(3)                                                |99
|       c = ','||c3||c                                                 |00
|       a = a.left(a.length() - 3)                                     |01
|     end                                                              |02
|     return a||c||b                                                   |03
|                                                                      |04
+----------------------------------------------------------------------+
                                                xmath.nrx(Method:dotify)
Download the complete source for the xmath.nrx library

Convert numbers in Computer Units.

Another usual conversion is to take a number and express it in Computer Units (K (kilo), M (mega), G (giga), etc.)

 
n                    cu
----------        -----
       452     ->   452
      1025     ->    1K
   1000000     ->  976K   ( why ??? )
 

The following function will do this.

 
+----------------------------------------------------------------------+
| -- method......: n2cu                                                |27
| -- purpose.....: convert n to Computer Units                         |28
| --                                                                   |29
|   method n2cu(n=Rexx) public static                                  |30
|     numeric digits 32        -- set high precision                   |31
|     list = 'K M G T P'       -- Kilo Mega Giga Tera Peta             |32
|     base = 1                                                         |33
|     max  = 1024                                                      |34
|     unit = ''                                                        |35
|     loop forever                                                     |36
|       if n < max then                                                |37
|         do                                                           |38
|           out = (n%base)||unit                                       |39
|           leave                                                      |40
|         end                                                          |41
|       parse list unit list   -- get next unit, pls                   |42
|       base = max                                                     |43
|       max = max*1024                                                 |44
|     end                                                              |45
|     numeric digits 9                                                 |46
|     return out                                                       |47
|                                                                      |48
+----------------------------------------------------------------------+
                                                  xmath.nrx(Method:n2cu)
Download the complete source for the xmath.nrx library

Call example:

 
say 'File size is' xmath.n2cu(size)'.'
 

Convert seconds to hours.

That's my last favourite conversion routine. I use it to convert seconds to a more readable human format.

 
s                    h
------     -----------
  7272  ->     2:01:12
100000  -> 1d-03:46:40

 

 
+----------------------------------------------------------------------+
| -- method......: s2h                                                 |49
| -- purpose.....: convert seconds to hours (or days)                  |50
| --                                                                   |51
|   method s2h(s=Rexx) public static                                   |52
|     h = s%3600                                                       |53
|     s = s//3600       -- modulo                                      |54
|     m = s%60                                                         |55
|     s = s//60         -- modulo                                      |56
|     if h > 24 then    -- express h in DAYSd-HH                       |57
|       do              -- if necessary                                |58
|         d = h%24                                                     |59
|         h = h//24                                                    |60
|         h = h.right(2,'0')                                           |61
|         h = d'd-'h                                                   |62
|       end                                                            |63
|     m = m.right(2,'0')                                               |64
|     s = s.right(2,'0')                                               |65
|     out = h':'m':'s                                                  |66
|     return out                                                       |67
|                                                                      |68
+----------------------------------------------------------------------+
                                                   xmath.nrx(Method:s2h)
Download the complete source for the xmath.nrx library

Call example:

 
say 'Time elapsed' xmath.s2h(sec)'.'
 

Chapter FAQ

QUESTION: How do I round-up a number? As we saw, the '/' divide operator does a 'crude and simple' truncation on the result. If you need a real round up, then you should use the format(NULL,0) instruction, like in the following example:

 
rounded = n.format(NULL,0)
 

You can try out the following code to test yourself.

 
+----------------------------------------------------------------------+
| -- Round up example                                                  |01
| --                                                                   |02
| parse arg n1 n2                                                      |03
| n3 = n1/n2                                                           |04
| say 'Result:' n3                                                     |05
| say 'Round :' n3.format(NULL,0)                                      |06
| exit 0                                                               |07
+----------------------------------------------------------------------+
                                                             roundup.nrx
Download the source for the roundup.nrx example

Summary

We resume what we've seen so far in this chapter.

 
_ basic operations                | + - * /
                                  | - ex.: a+b
                                  |
_ setting precision               | Numeric Digits NN
                                  | - ex.: Numeric Digits 20
                                  |
_ query precision                 | digits
                                  | - ex.: nn = digits
                                  |
 

 
 *** This section is: 
  
 *** and will be available in next releases


File: nr_7.html.

The contents of this WEB page are Copyright © 1997 by Pierantonio Marchesini / ETH Zurich.

Last update was done on 18 May 1998 21:47:38(GMT +2).