# Operators and logical expressions

## Contents

- Operators

- Arithmetic operators
- Comparison operators
- Logical and bitwise operators
- The `%` operator
- Precedence
- When there is equal precedence
- Changing precedence with brackets
- Precedence of integer and floating-point values
- Type conversions and rounding down

- Logical expressions
- Logical and bitwise operators

- When used with floating-point numbers
- When used with integer or long integer values

## Operators

Section Contents

- Arithmetic operators
- Comparison operators
- Logical and bitwise operators
- The `%` operator

- Examples:

- Precedence
- When there is equal precedence
- Changing precedence with brackets
- Precedence of integer and floating-point values
- Type conversions and rounding down

These operators are available in OPL:

### Arithmetic operators

`+` | add
`-` | subtract
`*` | multiply
`/` | divide
`**` | raise to a power
`-` | unary minus (in negative numbers for example, `-10`)
`%` | percent
`MOD` | modulo — the remainder of the division of two numbers

### Comparison operators

`>` | greater than
`>=` | greater than or equal to
`<` | less than
`<=` | less than or equal to
`=` | equal to
`<>` | not equal to

### Logical and bitwise operators

`AND` | logical AND
`OR` | logical OR
`NOT` | logical NOT
`XOR` | exclusive OR

### The `%` operator

The percentage operator can be used in expressions like this:

Expression | Meaning | Result
`60+5%` | 60 plus 5% of 60 | 63
`60-5%` | 60 minus 5% of 60 | 57
`60*5%` | 5% of 60 | 3
`60/5%` | of what number is 60 5%? | 1200

It can also be used like this:

`105>5%` | what number, when increased by 5%, becomes 105? | 100
`105<5%` | how much of 105 is a 5% increase? | 5

#### Examples:

To add 15% tax to 345:

`345+15%` Result = 396.75

To find out what the price was before tax:

`396.75>15%` Result = 345

To find out how much of a total price is tax:

`396.75<15%` Result = 51.75

### Precedence

Highest: | `**`
| `-` (unary minus)
| `NOT`
| `* /`
| `+ -` (subtraction)
| `= > < <> >= <=`
Lowest: | `AND OR`

So `7+3*4` returns 19 (3 is first multiplied by 4, and 7 is added to the result) not 40 (4 times 10).

### When there is equal precedence

In an expression where all operators have equal precedence, they are evaluated from left to right (with the exception of powers). For example, in `a+b-c`, `a` is added to `b` and then `c` is subtracted from the result.

Powers are evaluated from right to left for example, in `a%**b%**c%`, `b%` will first be raised to the power of `c%` and then `a%` will be raised to the power of the result.

### Changing precedence with brackets

The result of an expression such as `a+b+c` is the same whether you first add `a` to `b`, or `b` to `c`. But how is `a+b*c/d` evaluated? You may want to use brackets to either:

- Make it obvious what the order of calculation is

or

- Change the order of calculation.

By default, `a+b*c/d` is evaluated in the order: `b` multiplied by `c`, then divided by `d`, then added to `a`. To perform the addition and the division before the multiplication, use brackets: `(a+b)*(c/d)`. When in doubt, simply use brackets.

### Precedence of integer and floating-point values

You are free to mix floating-point and integer values in expressions, but be aware how OPL handles the mix:

- In each part of the calculation, OPL uses the simplest arithmetic possible. Two integers will use integer arithmetic, and this can give unexpected results: `7/2` gives the integer `3`. Otherwise floating-point arithmetic is used (`7.0` is a floating-point number, so `7.0/2` gives the floating-point number `3.5`).
- Finally, the evaluated result of the right-hand side of an expression is automatically converted to the same type as the variable to which it is assigned.

For example, your procedure might include the expression `a%=b%+c` This is handled like this: `b%` is converted to floating-point and added to `c`. The resulting floating-point value is then automatically converted to an integer in order to be assigned to the integer variable `a%`.

Such conversions may produce odd results for example `a%=3.0*(7/2)` makes `a%=9`, but `a%=3.0*(7.0/2)` makes `a%=10`. OPL does not report this as an error, so it’s up to you to ensure that it doesn’t happen unless you want it to.

### Type conversions and rounding down

There are three numeric types floating-point, integer and long integer. You can assign any of these types to any other. The value on the right-hand side will be automatically converted to the type of the variable on the left-hand side. For example:

- If you assign an integer value to a floating-point variable, there are no problems.
- If you assign a floating-point value to an integer variable, the value is converted to an integer, always rounded towards zero for example, if you declare `LOCAL c%` and then say `c%=3.75`, the value `3.75` is converted to the value `3`.

Rounding down towards zero can sometimes cause unusual results. For example, `a%=2.9` would give `a%` the value 2, and `a%=-2.3` would give `a%` the value `-2`.

When you run a module, if the left-hand side of an assignment has a narrower range than the right-hand side, you may get an error (for example, if you had `x%=a&` where `a&` had the value `320000`).

To control how floating-point numbers are rounded when converted, use the INT function.

## Logical expressions

The comparison operators and logical operators are based on the idea that a certain situation can be evaluated as either true or false. For example, if `a%=6` and `b%=8`, `a%>b%` would be ‘False’.

These operators are useful for setting up alternative paths in your procedures. For example you could say:

        IF salary<expenses
              doBad:
        ELSE
              doGood:
        ENDIF

You can also make use of the fact that the result of these logical expressions is represented by an integer:

- ‘True’ is represented by the integer `-1`
- ‘False’ is represented by the integer `0` (zero).

operator | example | result returned | return value
< | `a<b` | True if `a` less than `b` | `-1`
|  | False if `a` greater than or equal to `b` | `0`
> | `a>b` | True if `a` greater than `b` | `-1`
|  | False if `a` less than or equal to `b` | `0`
<= | `a<=b` | True if `a` less than or equal to `b` | `-1`
|  | False if `a` greater than `b` | `0`
= | `a>=b` | True if `a` greater than or equal to `b` | `-1`
|  | False if `a` less than `b` | `0`
<> | `a<>b` | True if `a` not equal to `b` | `-1`
|  | False if `a` equal to `b` | `0`
= | `a=b` | True if `a` equal to `b` | `-1`
|  | False if `a` not equal to `b` | `0`

These integers can be assigned to a variable or displayed on the screen to tell you whether a particular condition is true or false, or used in an IF statement.

For example, in a procedure you might arrive at two sub-totals, `a` and `b`. You want to find out which is the greater. So use the statement, `PRINT a>b`. If zero is displayed, `a` and `b` are equal or `b` is the larger number; if -1 is displayed, `a>b` is true `a` is the larger.

## Logical and bitwise operators

Section Contents

- When used with floating-point numbers
- When used with integer or long integer values

- AND
- OR
- NOT

The operators AND, OR and NOT have different effects depending on whether they are used with floating-point numbers or integers:

### When used with floating-point numbers

AND, OR and NOT are logical operators, and have the following effects:

example | result | integer returned
`a AND b` | True if both `a` and `b` are non-zero | `-1`
| False if either `a` or `b` are zero | `0`
`a OR b` | True if either `a` or `b` is non-zero | `-1`
| False if both `a` and `b` are zero | `0`
`NOT a` | True if `a` is zero | `-1`
| False if `a` is non-zero | `0`

### When used with integer or long integer values

AND, OR and NOT are bitwise operators.

The way OPL holds integer numbers internally is as a binary code - 16-bit for integers, 32-bit for long integers. Bitwise means that an operation is performed on individual bits. A bit is set if it has the value 1, and clear if it has the value 0. Long integer values with AND, OR and NOT behave the same as integer values.

#### AND

Sets the result bit if both input bits are set, otherwise clears the result bit.

For example, the statement `PRINT 12 AND 10` displays 8. To understand this, write 12 and 10 in binary:

`12 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
10 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0`

AND acts on each pair of bits. Thus, working from left to right discounting the first 12 bits (since `0 AND 0` gives 0):

`1 AND 1` `1`
`1 AND 0` `0`
`0 AND 1` `0`
`0 AND 0` `0`

The result is therefore the binary number 1000, or 8.

#### OR

Sets the result bit if either input bit is set, otherwise clears the result bit.

What result would the statement `PRINT 12 OR 10` give? Again, write down the numbers in binary and apply the operator to each pair of digits:

`1 OR 1` `1`
`1 OR 0` `1`
`0 OR 1` `1`
`0 OR 0` `0`

The result is the binary number 1110, or 14 in decimal.

#### NOT

Sets the result bit if the input bit is not set, otherwise clears the result bit.

NOT works on only one number. It returns the one’s complement, i.e. it replaces 0s with 1s and 1s with 0s.

So since 7 is 0000000000000111, `NOT 7` is 1111111111111000. This is the binary representation of -8.

A quick way of calculating NOT for integers is to add 1 to the original number and reverse its sign. So `NOT 23` is -24, `NOT 0` is -1 and `NOT -1` is 0.