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:
PRINT 2+2
The ugBASIC language 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 double asterisk sign for multiplication with a number that is a power of 2 (very fast on CPU);/
: the forward-slash symbol for division;\
: the backward-slash symbol for division with a number that is a power of 2 (very fast on CPU);^
: the circumflex character as exponential symbol (raise this number to a given power);a = 3^5
b = 3*3*3*3*3
MOD
: is the "modulo" operator;NOT
: is the bit a bit / logical not;AND
: is the bit a bit / logical and;OR
: is the bit a bit / logical or;XOR
: is the bit a bit / logical exclusive or;FALSE
is associated with a number composed of
all 0
s, in terms of bits. The value TRUE
is, instead,
associated with a number composed of all 1
s, again in terms of bits.
According to the 2's complement representation, a number composed of all ones is
always equivalent to the number -1
, regardless of how many bits the
number is composed of, while a number composed of all zeros is always equivalent to zero.AND
, applied to all the bits of the number,
will be equivalent to the logical operation "and". And so with the remaining bitwise
(/logical) operations.
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:
PRINT 2+2*2 : REM Print 6
PRINT (2+2)*2 : REM Print 8
The ugBASIC language 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;NOT
, AND
, OR
, XOR
)
will not be taken into account until after all the above calculations have been completed. Obviously,
any calculation placed inside a pair of round brackets is evaluated first, and treated as a single number.PRINT 10+2*5-8/4+5^2 : REM Print 43
5^2 = 25
2*5 = 10
8/4 = 2
10+10 = 20
20-2 = 18
18+25 = 43
768
(!), like this:PRINT (10+2)*(5-8/4+5)^2 : REM Print 768
10+2 = 12
5-8/4+5 = 5-2+5
5-2+5 = 8
8^2 = 64
12*64 = 768
Mathematical calculations typically generate a series of intermediate values,
and can therefore sometimes be a little slow. There are three instructions that
can be used to increase the speed when it is present a simple calculation:
INC
- to increment a variable by 1;DEC
- to decrement a variable by 1;ADD
- to 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.v=41 : INC v : PRINT v
INC
, the DEC
command performs a rapid subtraction
of 1 from an integer variable.v=43 : DEC v : PRINT 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 is faster. There is a more complex version of ADD
, which
is ideal for handling certain limits much more quickly than the equivalent separate instructions.
When those other parameters are included,ADD v,a,b TO t
v=v+a
IF v<b THEN v=t: ENDIF
IF v>b THEN v=b: ENDIF
v=0
REPEAT
ADD v,1,1 TO 42
PRINT 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.
PRINT MAX(99,1) : REM Print a 99
PRINT 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
(in hexadecimal). 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 two's 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:
00
to 7F
,
regardless of whether the number is signed or unsigned;SGN
function returns a
value representing the sign of a number. The three possible results are these:-1
if the value is negative;1
if the value is positive;0
if the value is zero.PRINT SGN(-42): REM Print -1
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.PRINT ABS(-1): REM Print 1
PRINT 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.
The 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.
DO
x = RND(WIDTH-1): 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.
The TIMER
reserved variable is incremented by 1 unit every 50th of
a second (on PAL systems) or by 1 unit every 60th of second (on NTSC systems), 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:
RANDOMIZE TIMER
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.
If you have found a problem, if you think there is a bug or, more
simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.
Thank you!