This section provides a full explanation of using standard mathematical and trigonometric functions, as well an insight into how ugBASIC exploits numbers.
Traditional mathematical operation is very easy on ugBASIC, since it gives to the programmer all basic arithmetical operations. For example, this instruction will print out a simple
4 as a result:
ugBASIC recognize various mathematical symbols, as follows:
+the plus sign that always signals addition;
-the minus sign, used for subtraction;
*the asterisk sign for multiplication;
/the forward-slash symbol for division.
^the circumflex character as exponential symbol (raise this number to a given power);
The following two lines are equal:
a = 3^5 b = 3*3*3*3*3
The following logical operations can also be used in calculations:
MODis the “modulo” operator, which acts as a constant multiplier.
ANDis the logical and;
ORis the logical or;
XORis the logical exclusive or.
Since arithmetical instructions are taken literally, ugBASIC uses a set of built-in priorities. So the following lines give the results 6 and 8, respectively:
DEBUG 2+2*2 : REM Print 6 DEBUG (2+2)*2 : REM Print 8
ugBASIC handles a combination of calculations that make up an “expression” in the following strict order of priority:
^) are always calculated first ;
*) and divisions (
/) are then calculated in order of appearance, from left to right;
MOD) is elaborated;
+) and subtractions (
-) are calculated last, again in order, from left to right.
Logical operations will not be taken into account until after all the above calculations have been completed (AND, OR, XOR). Obviously, any calculation placed inside a pair of round brackets is evaluated first, and treated as a single number. So the next calculation gives a result of 43:
DEBUG 10+2*5-8/4+5^2 : REM Print 43
This is the order followed:
5^2 = 25 2*5 = 10 8/4 = 2 10+10 = 20 20-2 = 18 18+25 = 43
By adding two strategic pairs of brackets to the same calculation, the logical interpretation is transformed, resulting in an answer of 768 (!), like this:
DEBUG (10+2)*(5-8/4+5)^2 : REM Print 768
This is the different order followed:
10+2 = 12 5-8/4+5 = 5-2+5 5-2+5 = 8 8^2 = 64 12*64 = 768
There are three instructions that can be used to increase the speed when it is present a simple calculation:
INCto increment a variable by 1
DECto decrement a variable by 1
ADDto add any number to a variable
INC command adds 1 to an variable, using a single instruction to perform the expression
variable=variable+1 very quickly. For example:
v=41 : INC v : DEBUG v
DEC command performs a rapid subtraction of 1 from an integer variable.
v=43 : DEC v : DEBUG v
ADD command can be used to add the result of an expression to a whole number variable. It is the
equivalent to make a
variable=variable+expression but performs the addition faster. There is a more complex version of
ADD, which is ideal for handling certain loops much more quickly than the equivalent separate instructions. When those other parameters are included,
ADD v,a,b TO t is the equivalent to the following lines:
v=v+a IF v<b THEN v=t: ENDIF IF v>t THEN v=b: ENDIF
Here is an example:
v=0 REPEAT ADD v,1,1 TO 42 DEBUG v UNTIL v == 43 : REM This loop is infinite because v < 43
It is obvious that every expression has a value, but expressions are not restricted to whole numbers (integers), or any sort of numbers. Expressions can be created from real numbers or strings of characters. If you need to compare two expressions, the following functions are provided to examine them and establish their relative values.
MAX compares two expressions and returns the largest. It can be used with any type of expressions, but they cannot be compared if they are mixed.
DEBUG MAX(99,1) : REM Print a 99 DEBUG MAX("ugBASIC","AAAA") : REM Print "ugBASIC"
On the very same way,
MIN compares two expressions and returns the smaller value of two expressions.
DEBUG MIN(99,1) : REM Print a 1 DEBUG MIN("ugBASIC","AAAA") : REM Print "AAAA"
To explain how ugBASIC treats signed numbers, it is necessary to make a brief excursus on the concept of “two's complement”. There are 256 possible values in a byte: $00 to $FF. The range of an 8-bit unsigned number is 0 ($00) to 255 ($FF). The range of a 16-bit unsigned number is 0 ($0000) to 65535 ($FFFF), and so on. They are called unsigned numbers because they are zero or greater, i.e. there is no (minus) sign.
A signed number, on the other hand, can be negative or positive (or zero). The term “signed number” is used below to mean a twos complement number, so the range of an 8-bit signed number is -128 to 127. The values -128 through -1 are, in hex, $80 through $FF, respectively. The values 0 through 127 are, in hex, $00 through $7F, respectively. So the minimum value of a signed number is $80 and the maximum value of a signed number is $7F. The range of a 16-bit signed number is -32768 ($8000) to 32767 ($7FFF) ($8000 through $FFFF are the negative numbers), and so on.
This may seem like a strange way of handling negative numbers, but this method has several useful properties:
Any number can have one of three values: negative, positive or zero, and these are represented by the “sign” of a
number. So the
SGN function returns a value representing the sign of a number. The three possible results are these:
DEBUG SGN(-42): REM Print -1
On the other side,
ABS can be used to convert arguments into a positive number. ABS returns an absolute value of an integer or fractional number, paying no attention to whether that number is positive or negative, in other words, ignoring its sign.
DEBUG ABS(-1): REM Print 1 DEBUG ABS(1): REM Print 1
The easiest way to introduce an element of chance or surprise into a program is to throw some numbered options into an electronic “pot” and to allow ugBASIC to pull one out at random. After a number has been selected and used, it is thrown back into the pot once again. It then has the same chance as any other number offered for selection, when the next random choice is made.
RND function generates integers at random, between zero and any number specified in brackets. If your
specified number is greater than zero, random numbers will be generated up to that maximum number. However, if
you specify 0, then
RND will return the last random value it generated. This is useful for debugging programs.
DO x = RND(WIDTH): REM you can use "RANDOM WIDTH" as an alternative y = RND(HEIGHT-1): REM you can use "RANDOM HEIGHT" as an alternative TEXT x, y, "UGBASIC AT RANDOM" LOOP
In practice, the numbers produced by the
RND function are not genuinely random at all. They are computed by an internal mathematical formula, whose starting point is taken from a number known as a “seed”. This seed is set to a standard value whenever ugBASIC is loaded into your computer, and that means that the sequence of numbers generated by the
RND function will be exactly the same each time your program is run.
This may well be acceptable for arcade games, where pre-set random patterns generated by
RND can be used to advantage, but it is a useless system for more serious applications. The
RANDOMIZE command solves this problem by setting the value of the seed directly. This seed can be any value you choose, and each seed will generate an individual sequence of numbers.
RANDOMIZE can also be used in conjunction with the
TIMER variable, to generate genuine random numbers.
TIMER reserved variable is incremented by 1 unit every 50th of a second, in other words, it returns the amount of time that has elapsed since your computer was last switched on. As explained above, this makes it a perfect “seed” to be used with the
RANDOMIZE function, as follows:
The best place to use this technique is immediately after the user has entered some data into the computer. Even a simple key-press to start a game will work perfectly, and generate truly random numbers.