# Values and expressions

## Contents

- Overview
- Values

- Types of value

- Constants and variables — Storing values for later use

- Variables
- Constants

- Expressions — Manipulating and combining values

- Arithmetic operations
- Values from functions
- Problems with integers
- Operations on strings

## Overview

This section covers the basic OPL constructions that can be used within a procedure. It describes the basic ways in which programs can deal with data, store and retrieve it, manipulate it and combine it.

See also: Control structures, Commands.

## Values

Section Contents

- Types of value

- Number values
- Text values

Before using a value, you must decide what sort of information you need to represent, and to some extent what you need to do with the data. There are different types of value for different tasks and uses.

Each value in an OPL program has a type associated with it. If you try to use the wrong type of value in a place where a particular type of variable is expected, an error message will be displayed when you try to translate your program.

The numbers and strings in quote marks written in an OPL program are sometimes called literals. In practice, you will use literal values without thinking about them. For example:

`0.32` | Floating-point number.
`569` | Integer.
`32768` | Long integer.
`$2b` | Integer, specified in hexadecimal.
`"hello"` | String.

You can only use these values in a statement — such as `print "hello world"` — so this section will use the `print` command when discussing values.

### Types of value

OPL can represent values of various kinds. Each value has an associated type.

Before using a value, decide what information you need to represent. There are different types of variables for different sorts of values. If you try to give the wrong type of value to a variable, an error message will be displayed.

#### Number values

- For small whole numbers — for example `6` — use the integer type.

Integers can only be used for numbers in the range -32768 to +32767.

- For larger whole numbers — for example `10000000` — use the long integer type.

Long integers can handle whole numbers in the range -2147483648 to +2147483647. If you may have to handle numbers outside normal integer range, use the long integer representation.

- For non-whole numbers — for example `2.5` — use the floating-point type.

Floating-point numbers can represent numbers from 2.2250738585072015E-308 to 1.7976931348623157E+308, and 0.

If you know that at some stage in your program your variable will have to handle non-whole numbers, like 1.2, use a floating-point, not an integer variable. Otherwise you may get unpredictable results. (There’s more about this later in this topic.)

For very large whole numbers outside long integer range you should also use floating-point variables.

When assigning numbers to a variable, you should ensure the variable is of the right type. You may get unpredictable results or translation errors if a variable is not of the right type for the value it is to store (see below).

##### Writing numbers

Besides writing simple decimal numbers as above, you can also write numbers in hexadecimal, or use exponential notation.

Integers specified in hexadecimal must be preceded by a `$` and long hex integers by a `&`. For example, `$f` or `&80000000`. This is explained under the `HEX$` entry in the Keyword Reference section.

Exponential notation may be useful for very large or very small numbers. Use `E` (capital or lower case) to mean “times ten to the power of” — for example, `3.14E7` is 3.14 x 107 (31400000), while `1E-9` is 1 x 10-9 (0.000000001).

##### More on number representation

It is possible to use the full available range of 64-bit floating-point values, i.e. all real numbers with absolute values in the range 2.2250738585072015E-308 to 1.7976931348623157E+308 and 0. Precision remains limited to about 15 significant figures in this range. It is also possible to use numbers which have absolute values in the range 5E-324 to 2.2250738585072015E-308 (called denormals), however the precision decreases in this range to only 1 significant figure at the lower end. It is possible to enforce the ranges used by earlier releases of OPL (see below) by using the `SETFLAGS` command. See the Keyword Reference section for details of this.

Constants for the maximum and minimum values of all variable types are given in `Const.oph`. See const.oph for more on this.

With `SETFLAGS KTwoDigitExponent&` in effect, floating-point variables can only represent numbers as big as 9.99999999999e99 and as small as 1e-99, and 0. Intermediate results in calculations (which are not displayed on the screen) may exceed this and can take any value in the full range of 64-bit floating point numbers as above.

#### Text values

For text — “Are you sure?”, “54th”, etc. — use a string variable.

To write a string, write the string in double quotes:

        print "some text"

A string can only be written on one line; it may contain no return characters. If you need to write a double quote character in a string, use `""`. OPL understands doubled `"`s in a string as single `"`s:

        print """This deck contains no twos"", Tom deduced."

## Constants and variables — Storing values for later use

Section Contents

- Variables

- Declaring variables
- Choosing names for variables
- Variable types
- Initial values
- Assignment — Putting a value in a variable
- Using variables — Getting a variable’s value

- Constants

- Declaring constants

OPL can store values and use them later by declaring that a name represents a particular value. This can be done in two ways, either by a variable or by a constant. Variables are used to store values which may change, and constants store fixed values.

### Variables

#### Declaring variables

Most procedures begin by declaring (creating) variables:

        LOCAL x,y,z

`LOCAL` is the keyword telling OPL to create variables, with the names which follow - here `x`, `y` and `z` — separated by commas. These variables initially have the value 0.

The statement `LOCAL x,y,z` declares three variables called `x`, `y` and `z`. OPL will recognise these names whenever you use them in this procedure. If you used them in another procedure, they wouldn’t be recognised; the variables are ‘local’ to the procedure in which they are declared.

Any variables you wish to use must be declared at the start of a procedure.

Variables can also be declared `GLOBAL` at the start of a procedure if you want them to be recognised by other procedures. See `GLOBAL` under Keyword Reference for more on this.

Two variables cannot have the same name. For example, it is not possible to write:

        PROC badProcedure:
              LOCAL x,y,z
              GLOBAL v,w,x  REM duplicate "x" value
        ENDP

This will display a `Duplicate name` error when you try to translate it.

#### Choosing names for variables

To make it easier to write your programs, and understand them when you read through them at a later date, give your main variables names which describe the values they hold. For example, in a procedure which calculates fuel efficiency, you might use variables named `speed` and `distance`.

All variable names:

- May be entered in any combination of upper and lower case. `sPeeD` and `SpEEd` would be considered the same name.
- Must not use any of the names of keywords, as listed in the Keyword Reference section. If you use these you will see a `Declaration error` message when you translate your module.
- May be up to 32 characters long
- Must start with either an underscore (_) or an alphabetic character, but after that may use any combination of numbers, letters and the underscore character.

The `$`, `&` and `%` symbols (see Variable types, below) are included in the 32 characters allowed in variable names, so `V2345678901234567890123456789012%` is too long to be a valid variable name, but `V234567890123456789012345678901%` is acceptable.

When variables are declared, they automatically get a default value. See Initial values.

#### Variable types

The types a variable can have correspond to the types of value OPL can represent (see Types of value, above)

##### Scalar variables

Simple numbers and strings are called scalar values. You give the type of a variable by appending a type character onto the end of the variable name:

Type character | Variable type | Example declaration
(nothing) | Floating-point. | `LOCAL aFloating`
`%` | Integer. | `LOCAL anInteger%`
`&` | Long integer. | `LOCAL aLong&`
`$` | String. | `LOCAL aString$`

##### Array variables

You may want a group of variables, for example to store lists of values. Instead of having to declare separate variables `a`, `b`, `c`, `d` and `e`, you can declare array variables `a(1)` to `a(5)` in one go like this:

`LOCAL a%(5)` | Array of integer variables.
`LOCAL a(5)` | Array of floating-point variables.
`LOCAL a$(5,8)` | Array of string variables (note the second number).
`LOCAL a&(5)` | Array of long integers.

The number in brackets is the number of elements in the array. So `LOCAL a%(5)` creates five integer variables: `a%(1)`, `a%(2)`, `a%(3)`, `a%(4)` and `a%(5)`.

With strings, the second number in the brackets specifies the maximum length of the strings. All the elements in the string array have the same capacity — for example, `LOCAL ID$(5,10)` allocates memory space for five strings, each up to 10 characters in length.

OPL does not support two-dimensional arrays.

##### For efficiency

- Integer variables use less memory than long integer variables, and both use less than floating-point.
- Integer variables are processed very much faster than floating-point.

However, the cardinal rule is still to use the right kind of variable for the values you want to store. If a number needs to represent non-integer quantities, use a floating-point variable to store it, and if it needs to represent large numbers, use a long integer or a floating-point number as appropriate.

#### Initial values

When a variable is declared, it automatically has some default value. For numeric values, the initial value is zero. For strings, the initial value is the empty string (written `""`).

#### Assignment — Putting a value in a variable

Values can be assigned to a variable using an assignment statement. This is the variable name, an equals sign, and the value you want to assign to the variable. Examples are:

        a%=42
        profit=378.373721
        greeting$="Good day!"
        bignum&=65535+2001-(42*3)

In assignment statements, the variable assigned to can be used in the expression to the right of the equals sign. Expressions are covered below.

`z%=z%+1` | makes the value of `z%` one greater than its current value
`x%=(x%/4)+y%` | makes the value of `x%` a quarter of its current value, plus the value of `y%`

#### Using variables — Getting a variable’s value

A variable name can be used anywhere you’d normally use a variable of the appropriate type. For example:

        PROC test1:
              LOCAL i%
              i% = 42
              PRINT 42+7
              PRINT i%+7
              GET        REM Wait for a keypress
        ENDP

This example prints `49` twice, because `i%` was assigned the value `42`.

### Constants

Constants are essentially variables whose values can never change. They are used exactly like variables (see Using variables — Getting a variable’s value, above), but their declaration is different.

Using constants allows you to assign a name to a value so it may be used throughout the module. If you need to use a particular value several times in your program, it is easier to define it as a constant and use its name rather than spelling it out in full every time you need to use it. Also, if the value you need to use changes during your program’s development, it is far easier to change a single value at the top of a module than it is to change every occurrence of a value in the program.

Constants can be shared between modules, and there are several standard OPL values defined in `Const.oph`. See Including header files for more on how to use this.

By convention, all constants are named with a leading `K` to distinguish them from variables.

#### Declaring constants

Constants are declared with the `CONST` keyword. Because their value never changes, constants must be assigned a value where they are declared:

        CONST KMinimumTemp%=-237

Constants must be declared outside procedures. You will get a translation error if you try to declare a constant inside a procedure.

The names of constants must not clash with those of variables declared with `LOCAL` or `GLOBAL`. It’s usual to add a `K` prefix to the constant name. This helps avoid name clashes, and is also a useful reminder that you can’t change the name’s value when you use it.

## Expressions — Manipulating and combining values

Section Contents

- Arithmetic operations
- Values from functions
- Problems with integers
- Operations on strings

Expressions are combinations of numbers, variables, and functions that the interpreter can use as a value. An example of an OPL statement using an expression is:

        print 42+(2*3)

The value of the expression `42+(2*3)` is 48, so the statement prints `48` to the text display.

Expressions can be built from other expressions (sub-expressions) as well as values: notice that in the example above, `(2*3)` is a sub-expression. Expressions can be as complex as you like, although it’s a good idea to keep things reasonably simple so you can understand them later.

Expressions can be used anywhere OPL expects a value. Types of expression include operations on values, and function calls.

For example:

`z=x+y/2` | gives `z` the value of `x` plus the value of `y/2`.
`z=x*y+34.78` | gives `z` the value of `x` times `y`, plus `34.78`.
`z=x+COS(y)` | gives `z` the value of `x` plus the cosine of `y`.

`COS(y)` in the example above is a function call — see Values from functions below.

### Arithmetic operations

You can use these operators:

`+` | Plus. | x%+13
`-` | Minus (or make negative). | -70-32.8
`/` | Divide. | 9/3
`*` | Multiply. | 9*5
`**` | Raise to a power. | 2**8
`%` | Percentage. | 17.5%

Operators have the same precedence as in the `Calc` application. For example, `3+51.3/8` is treated as `3+(51.3/8)`, not `(3+51.3)/8`. For more information on operators and precedence, see Operators and logical expressions.

### Values from functions

There are two kinds of keyword — commands and functions:

- A command is just a straightforward instruction to OPL to do some particular thing. `PRINT` and `PAUSE`, for example, are commands.
- A function is just like a command but it also returns a value which you can then use.

`GET` (as used above) is, in fact, a function; it waits for you to press a key on the keyboard, and then returns a value which identifies the key which was pressed. In previous example programs, the value returned by `GET` was ignored, as `GET` was being used to provide a pause while you read the screen. This is a common use of the `GET` function.

The number returned by `GET` will always be a small whole number, so you might store it away in an integer variable, like this:

        a%=GET

There is more about the `GET` function later in this topic.

        a%=COS(b)

`COS` is another OPL function. Unlike the GET function, `COS` requires a value or variable to work with. As you can see, you put this in brackets after the function name. Values you give to functions in this way are called arguments to the function. There is more information about arguments in Commands.

### Problems with integers

When calculating an expression, OPL uses the simplest arithmetic possible for the numbers involved. If all of the numbers are integers, integer arithmetic is used; if one is outside integer range, but within long integer range, then long integer arithmetic is used; if any of the numbers are not whole numbers, or are outside long integer range, floating-point arithmetic is used.

This has the benefit of maximising speed, but you must beware of calculations going out of the range of the type of arithmetic used. For example, in `X=200*300` both `200` and `300` are integers, so integer arithmetic is used for speed (even though `X` is a floating-point variable). However, the result, 60000, cannot be calculated because it is outside integer range (32767 to -32768), so an ‘Overflow’ error is produced.

You can get around this by using the `INT` function, which turns an integer into a long integer, without changing its value. If you rewrite the previous example as `X=INT(200)*300`, OPL has to use long integer arithmetic, and can therefore give the correct result (60000). (If you understand hexadecimal numbers, you can instead write one of the numbers as a hexadecimal long integer, e.g. `200` would become `&C8`.)

Integer arithmetic uses whole numbers only. For example, if `y%` is 7 and `x%` is 4, `y%/x%` gives 1. However, you can use the INTF function to convert an integer or long integer into a floating-point number, forcing floating-point arithmetic to be used for example, `INTF(y%)/x%` gives 1.75.

This rule applies to each part of an expression — e.g. `1.0+2/4` works out as `1.0+0` (=1.0), while `1+2.0/4` works out as `1+0.5` (=1.5).

If one of the integers in an all-integer calculation is a constant, you can instead write it as a floating-point number. 7/4 gives 1, but 7/4.0 gives 1.75.

### Operations on strings

If `a$` is `"down"` and `b$` is `"wind"`, then the statement `c$=a$+b$` means `c$` becomes `"downwind"`.

Alternatively, you could give `c$` the same value with the statement `c$="down"+"wind"`.

When adding strings together, the result must not be longer than the maximum length you declared e.g. if you declared `LOCAL a$(5)` then `a$="first"+"second"` would cause a `String is too long` error to be displayed.

Most operators do not work on strings. To cut up strings, use string functions like `MID$`, `LEFT$` and `RIGHT$`, explained in the Keyword Reference section. You need these functions to extract even a single character — you cannot, for example, refer to the fourth character in `a$` as `a$(4)`.