next up previous contents
Next: Infix predicates on Up: CHAPTER.5: NUMERICAL AND Previous: Basic arithmetical facilities

Arithmetical operators

OPERATOR PRECEDENCE DESCRIPTION
    +       5       add two numbers
    -       5       subtract two numbers, or negate one number.
        (The syntactic context is used to determine whether this is
         a binary subtraction operator or a unary negation operator)
    *       4       multiply two numbers
    **      3       exponentiation:
                        e.g. A ** 3 means A*A*A i.e. A cubed.
    /       4       divide first number by second (See note below)
    //      4       divide first number by second, produce
                        remainder and quotient.

 X div Y    2       returns the number of times Y goes into X
 X rem Y    2       returns the remainder on dividing X by Y.
 X mod Y    2       returns the remainder on dividing X by Y.
        mod, unlike rem, requires both numbers to be real, i.e.
        non-complex. It always returns a result with the same sign as Y

Examples of arithmetical expressions

Here are some expressions formed using arithmetic operators:

    3 + 5 * 2 =>
    ** 13

    (3 + 5) * 2 =>
    ** 16
The expression:

    (X + Y) * (99 - Z/3)
has many sub-expressions, e.g. X, Y, 99, Z, 3, X + Y, Z/3, etc.

Notice how parentheses can affect the order in which operations are applied.

Illustrating the use of // (which produces two results)

The operator // is unusual in that it produces two results. It takes two integers, and produces two integers, a remainder and a divisor, as in:

    10 // 3 =>
    ** 1 3

    23 // 10 =>
    ** 3 2
Thus one can do things like

    vars remainder, quotient;  223 // 10 -> (remainder, quotient);
    remainder, quotient =>
    ** 3 22
or, combinding the declaration with a multiple initialisation:

    vars (remainder, quotient) = 223 // 10;
To illustrate the use of // on different kinds of numbers:

Dividing integers

    10 // 3 =>
    ** 1 3
    10 // -3 =>
    ** 1 -3
    -10 // 3 =>
    ** -1 -3
    -10 // -3 =>
    ** -1 3

Dividing decimals (or ddecimals)
    10.5 // -3.2 =>
    ** 0.9 -3

Dividing ratios
    (7/3) // (11/23) =>
    ** 29_/69 4

Dividing complexes
    (33 + sqrt(-57)) // sqrt(-5) =>
    ** 1.69505_+:0.841633 3_-:14

Binary and unary negation

Most of the above are `binary' operations. That is, they require TWO arguments. For example the expression

    3 + 4
applies the operation + to the two arguments 3 and 4. It denotes the number 7. The arguments may themselves be complex expressions, e.g.

    (3 + 4) + (5 + 6)
The operation - can be binary (two arguments) or unary (one argument), and Pop-11 works out from the context which it is. When it is unary, as in

    - 4
or

    - (3 + 5)
it produces a number by NEGATING its argument.

When it is a binary operator, as in

    3 - 4
or

    (2 + 1) - (2 + 2)
it subtracts the second argument from the first. So the latter denotes the number -1.

Roughly, the rule is that if "-" occurs as part of an expression in which it is immediately preceded by an expression, and not a comma, semicolon, or opening bracket of any kind, then it is treated as binary and represents a subtraction. Otherwise it is unary and represents a negation (change of sign).

The following are all binary (i.e. subtractions)

    x - y,    (33 * x) - sqrt(y),   x + y - z,  x * y - z - 1
The following are all unary (i.e. negation)

    -3 + 5,   sqrt(- 22),  if x > 0 then -x else x endif
One consequence of this is that although the other arithmetical operators can be used as normal functions, e.g.

    +(3, 5),  *(9, 10) =>
    ** 8 90
The minus symbol will normally be interpreted as a unary negation symbol in this sort of context, producing an unexpected result, e.g.

    -(6, 3) =>
    ** 6 -3
which is equivalent to

    6, -3 =>
or

    6, 3, - =>
    ** 6 -3
However, according to the rule given, the following will work as a binary negation, which may also be surprising:

    6, 3 - =>
    ** 3
When unary negate is required, this can be specified unambiguously by invoking the procedure negate, e.g.

    3 + negate(4) * 5 =>
Compared with

    3 + -4 * 5 =>
Similarly, because "nonop -" is always taken to refer to the subtraction procedure, the name "negate" must be used when unary minus is to be given as argument to a procedure, e.g.

    maplist([ 1 2 3 4 5 6], negate) =>
    ** [-1 -2 -3 -4 -5 -6]
Compare using the subtraction operator concatenated with the sqrt procedure:

    define sqrt_sub = nonop - <> sqrt enddefine;

    sqrt_sub(8, 4) =>
    ** 2.0
Or the subtraction operator partially applied to 3:

    define sub_3 = nonop - (% 3 %) enddefine;

    sub_3(66) =>
    ** 63

    sub_3(5.4) =>
    ** 2.4

WARNING: division of integers using "/" can produce ratios

The division operator "/" when given two integers (or bigintegers) will will not produce a decimal or ddecimal as result, but an integer (or biginteger) or ratio. Thus

    10/5 =>
    ** 2

    10/6 =>
    ** 5_/3
The reason for printing out ratios in this way, i.e. with the numerator and denominator joined by "_/" is that this will allow them to be read in again as ratios without violating Pop-11's syntactic rules for lexical items, mentioned briefly in chapter 1, and described fully in REF ITEMISE

This sort of result of integer division can cause confusion if you are used to a language which in which non-integer results of division are automatically converted (i.e. coerced) to decimals (reals, floats). This means that if you require such conversion you should ensure that one of the arguments to "/" is a decimal. e.g.

    10/6.0 =>
    ** 1.66667
or

    10.0/6 =>
    ** 1.66667


next up previous contents
Next: Infix predicates on Up: CHAPTER.5: NUMERICAL AND Previous: Basic arithmetical facilities



Aaron Sloman
Fri Jan 2 03:17:44 GMT 1998