# Manipulating information

BASIC functions and operators have been introduced so far in an order and to a depth designed to suit the reader who is entirely new to BASIC.

This chapter describes functions in a little more detail, gathered into logical groups, so you can easily appreciate what functions are provided in any particular area. It is probably not worth reading about facilities that don't sound relevant to your particular needs, especially if this is your first time working through this user guide; you can always return to them later.

This is not a complete description of the facilities available: the more complex or less usefule functions are either not described at all here, or are only described in outline. For further information on any of the functions and operators, see you will need to refer to 'Mallard BASIC: Introduction and Reference'

## 5.1 Manipulating numeric information

### 5.1.1 Arithmetic

The facilities that you will use most frequently with numeric information have already been described: the arithmetic operators of addition (+), subtraction (-), multiplication (*) and division (/).

These operators all apply equally well to integers and floating point (single and double precision) arithmetic. There are two further operators, particularly suited to manipulating integers: \ which is used for integer division (it converts the numbers to integers before dividing and returns an integer result) and MOD, which returns the remainder after performing an integer division:

```    PRINT 7/2

3.5

PRINT 7\2

3

PRINT 7 MOD 2

1

```

### 5.1.2 Signs

To ensure that a number (expression, variable) is positive, use ABS. This converts a negative or positive number to a positive number of the same size.

To determine the sign of a number (expression, variable), use SGN. This returns 0 if the value is 0, -1 if it is negative, +1 if it is positive. This provides a convenient way of 'compressing' a value's range, for example:

```100 state\$(0) = "overdrawn"

110 state\$(1) = "nil stock"

120 state\$(2) = "in stock"

...

200 state = SGN(stock(item))+1

210 PRINT name\$(item);" is ";state\$(state)

```
etc.

### 5.1.3 Logarithms and exponentiation

There are two logarithmic functions, providing natural logarithms (LOG) and logarithms to base 10 (LOG10).

To convert a natural logarithm back to the corresponding number, use EXP.

To raise a number to a power, use the exponentiation operator, . For example, to print 7 to the 4.4th power:

```    PRINT 7  4.4

```

To convert a logarithm to base 10 back to the corresponding number, use 10x (where x is the logarithm).

Note: The character is the exact equivalent to the character used for the exponentiation operator used on many CP/M systems. If you load a program developed on another system and display it on the screen, any characters it contains will be shown as s. Similarly, if you load a program developed on the Spectrum onto a different computer, the s will be shown as s.

### 5.1.4 Trigonometry

BASIC provides three trigonometric functions, for converting angles (expressed in radians) into cosines, sines and tangents: COS, SIN and TAN. Each takes a single numeric argument, in brackets. For example:

```    opposite = adjacent*TAN(theta)

```

There is also a single function to convert a tangent to an angle (radians):

```   theta = ATN(opposite/adjacent)

```

You can, of couse, create further trigonometric functions from these three simple functions. For example, if you need the cotangent of an angle, you can obtain this by putting `1/TAN(theta)` into your expression.

Yet more trigonometric functions can be produced with the help of the other BASIC functions introduced in this chapter. For details, see Appendix IX of 'Mallard BASIC: Introduction and Reference' - or any good mathematics book!

### 5.1.5 Bitwise operations

A number of operators are provided to manipulate integer numeric information at the level of individual bits. The most useful are:

`NOT number`
invert each bit in the number
`number1 AND number2`
set bits to 0 unless 1 in both numbers
`number1 OR number2`
set bits to 0 unless 1 in either or both numbers
`number1 XOR number2`
set bits to 0 unless 1 in one number, 0 in the other

These operators are often used in relational expressions, to invert the sense of a test, for example:

```    WHILE NOT EOF(file%)

INPUT #file%,name\$

WEND

```

### 5.1.6 Random numbers

It is occasionally useful to generate a number whose value you cannot easily predict - a 'random number'. This is often required in statistical analysis, when generating passwords, or programming games. It is very difficult to generate entirely random numbers. The BASIC function RND generates 'pseudorandom' numbers in the range 0...1: these numbers are in an entirely predictable, but rather obscure sequence which will be good enough for most purposes. In general, each time you use RND, you get the next number in the sequence.

So if, for example, you want a random number between 0 and 5, you could obtain this by using:

```    random.number = RND * 5

```

### 5.1.7 Maxima and minima

If you want to pick out the highest value from a list, use MAX. For example:

```    PRINT "The winner is";MAX(mark(1),mark(2),mark(3),mark(4))

```

If the values are negative, the highest is the one which is least negative.

Similarly, to pick out the lowest (most negative) number from a list, use MIN.

## 5.2 Manipulating textual information

### 5.2.1 Assigning to string variables

To change the whole of a string variable, you will usually use an equals sign:

```    new.string\$= "New, new, new"

```

The alternative is to use the special keywords LSET and RSET. These assign one string to another in such a way that the length of the string is preserved by adding extra spaces either at the end of the string (LSET) or at the beginning (RSET). LSET and RSET are chiefly used to assign strings to the 'fields' of the records in a random access file. They are described in Chapter 6, on using disc files.

To change part of a string variable, use MID\$ on the lefthand side of an assignment:

```    date\$ = "xxxx March, 1989"

MID\$(date\$,1,4) = "21st"

PRINT date\$

21st March, 1989

```

The parameters to MID\$ specify the string variable, the starting position and the number of characters to be replaced.

### 5.2.2 Joining strings

The only operator that can be used with strings is the addition operator '+', which adds the string to its right onto the end of the string to its left. Note that this is quite different to adding two numeric values - contrast the result of executing the two following instructions:

```    PRINT "123"+"456"

PRINT 123+456

```

### 5.2.3 Splitting strings

BASIC provides three functions to extract part of the text from a string: LEFT\$, MID\$ and RIGHT\$.

• To extract the first n characters from a string, use LEFT\$(string\$,n).
• To extract the last n characters from a string, use RIGHT\$(string\$,n).
• To extract n characters starting from position s from a string, use MID\$(string\$,s,n). (The first character in the string is at position 1.)
• To extract all the characters starting from position s from a string, use MID\$(string\$,s).

### 5.2.4 Generating strings

Two functions are provided to generate strings by repeating a single character.

To produce a string of n spaces, use SPACE\$(n).

To produce a string of n characters with internal value c, use STRING\$(n, c).

To produce a string of n characters "z", use STRING\$(n, "z").

For example (where 42 is the internal value of *):

```    PRINT STRING\$(20,"*");"Hi!";STRING\$(20,42)

********************Hi!********************

```

### 5.2.5 String length

A string can be anything from 0 to 255 characters long. BASIC provides a function, LEN, that returns the length of the string that is its argument. This is particularly useful when you need to process the string a character at a time, such as in the following routine, which displays the string in `title\$` double-spaced across the screen:

```100 characters = LEN(title\$)

110 FOR a = 1 TO characters

120 PRINT MID\$(title\$,a,1);" ";

130 NEXT

140 PRINT

```

### 5.2.6 Searching strings

To check whether a string contains a particular sequence of characters, you can use INSTR. This takes the form:

```    INSTR([start,]string1\$,string2\$)

```

Start specifies where the string is to be searched from; if this is omitted or set to 1, the whole string will be searched.

String1\$ is the string to search. String2\$ is the string to search for in string1\$

INSTR returns a numeric result. If the result is 0 then string2\$ was not found in string1\$. Otherwise, the result returned is the position in string1\$ of the first occurrence of string2\$ at or after the start.

This function has a number of uses not immediately apparent. For example, in the following it is used to cater for the user typing options as upper or lower case letters:

```...

100 PRINT "A=abort, B=begin again, R=retry. Press a key."

120 IF answer\$ = "" THEN 110

140 IF code = 0 THEN GOTO 100

150 ON code GOSUB 500,500,600,600,900,900

```

### 5.2.7 Converting strings

Text strings, unlike keywords, will be stored as upper and lower case if that is how they are typed. BASIC provides two functions to convert strings from upper case (capitals) to lower case and vice versa.

To convert a string to all upper case, use UPPER\$(string\$). To convert a string to all lower case, use LOWER\$(string\$). For example:

```    PRINT UPPER\$("February 1989 Accounts BOOK")

FEBRUARY 1989 ACCOUNTS BOOK

```

Note that this conversion does not affect any symbols other than the letters 'a'-'z' or 'A'-'Z'.

Characters in text strings can have internal values in the range 0 to 255, but only characters 0-127 are defined by the ASCII standard. You may occasionally need to use strings in which the top bit has been set (for example, as a parity bit) but should now be ignored: use STRIP\$(string\$) to ensure that you are only using codes in the range 0 to 127.

## 5.3 Converting between different types of information

This section describes the functions provided to convert information between the four main forms in which it is stored: string, integer, single and double precision.

Many conversions are performed automatically - for instance, an integer value can simply be assigned to a double precision variable, or a double precision value to an integer variable without using any conversion function. There are two main reasons for using conversion functions: to convert between incompatible data types (numeric and string) and to force a particular conversion when it would not normally occur.

### 5.3.1 Converting between string and numeric

The individual characters in strings are stored as single bytes, with values in the range 0...255. A different character is displayed for each value. The value corresponding to a particular character is called the character's internal value. For example, the letter 'A' has an internal value of 65, the letter 'B' 66 and so on.

The function ASC returns the internal value for a given character, so that PRINT ASC("A") would print 65.

The function CHR\$ returns the character with a particular internal value, so that PRINT CHR\$(65) would print A.

Although numeric values are converted to the text equivalent automatically when printed, you cannot use strings as numbers or vice versa. To use a string (such as "1234") as a number, or a number (such as 1234) as a string, you must use a conversion function.

To convert a number to exactly the same representation as would be used to print it, use STR\$, for example: number\$ = STR\$(number)

To convert a text representation of a number to a number, use VAL, for example: number = VAL(number\$)

Other functions are provided to convert numeric values to decimal, octal and hexadecimal strings. These are described in 'Mallard BASIC: Introduction and Reference'.

Other functions are also provided to convert numeric values to and from compact string representations for use with disc data files. These are described in Section 6.3.

### 5.3.2 Converting between integer, single and double precision

When a numeric value of one type is assigned to a numeric variable of a different type, it is automatically converted to suit the new type. However, there are two occasions when you may want to use conversion functions: when the numeric value is not being assigned to a variable so conversion would not normally take place, and when the conversion that would take place is not as you want.

When assigning a floating point value to an integer, the value will normally be rounded to the nearest integer with the integer further away from zero being chosen in the case of a tie. Thus 4.5 would round to 5, while 4.49 would round to 4.

To convert a numeric value to integer, single or double precision (as if assigning it to a variable of that type), use CINT, CSNG or CDBL respectively. This may be needed to force an expression to be evaluated in a particular precision; for example, compare:
 Type a# = 1/10 with Type a# = CDBL(1)/10 Type PRINT a# Type PRINT a# 0.1000000014901161 0.1

In the first case the division is performed using single length arithmetic giving a single length result, which is then converted to double length when it is assigned to the double length variable a#. In the second case the CDBL in the expression converts the dividend to double length before the division, which means that the division is performed using double length arithmetic, giving a double length result. (Incidentally, the first case illustrates the inexact representation of decimal fractions as binary ones, by printing the single length value of 0.1 to sixteen decimal digits rather than the usual seven.)

Functions are also provided to round the floating point part of a number in other ways. These are INT, FIX and ROUND. The number remains floating point.

To round a number to the smaller integer, use INT. INT(3.9) will produce 3, while INT(-3.9) will produce -4.

To round a number simply by losing the decimal part, use FIX. FIX(3.9) will produce 3, while FIX(-3.9) will produce -3.

To round a number to a specified number of decimal places, use ROUND(number,places). For example, ROUND(3.335,3) would produce 3.34 while ROUND(-3.335,2) would produce -3.34. If omitted, places is taken as 0, so ROUND(3.335) produces 3.

If places is negative, it is taken as the number of digits to round to the left of the decimal place; for example, ROUND(12345,-2) gives 12300.