|
Mathematical and Logical Operators |
Operators are the symbols that perform operations on variables and values. They are the building blocks for doing math, making comparisons, and creating logic in your programs. This tutorial is broken down into three parts to make learning easy and fun.
These are the operators you use for basic arithmetic.
Example: Calculating a Shopping Bill
++ works on a numeric variable. On a dynamic variable it
looks at the value the variable holds when the statement runs: a number goes up
by 1, and a string raises a Datatype mismatch exception that a
when block can catch:
Output:
A minus sign in front of a value, or of a whole expression in parentheses, flips its sign:
Output:
These operators are used to compare values and combine conditions, which is essential for making decisions in your code.
Example: Qualifying for a Discount
When used with numeric values, these same operators perform bitwise operations. Each bit of the number is processed individually.
Example: Working with Flags
Sheerpower also supports more advanced logical operators. Their behavior is easiest to understand using "Truth Tables."
| X | Y | X XOR Y | X IMP Y | X EQV Y |
|---|---|---|---|---|
| TRUE | TRUE | FALSE | TRUE | TRUE |
| TRUE | FALSE | TRUE | FALSE | FALSE |
| FALSE | TRUE | TRUE | TRUE | FALSE |
| FALSE | FALSE | FALSE | TRUE | TRUE |
Sheerpower, like all programming languages, follows a specific order when evaluating expressions. This is called operator precedence. Understanding this order is crucial for getting the correct results.
()^* and Division /+ and Subtraction -
Example: In the expression 4 + 5 * 2, the
multiplication 5 * 2 happens first, resulting in 10. Then the
addition 4 + 10 is performed, giving a final result of 14.
To change this, you would use parentheses: (4 + 5) * 2, which
evaluates to 18.
The pipeline operator |> takes the value
on its left and passes it to the function on its right as that
function's first argument. It works with any function
— math, string, or user-defined.
Without the pipeline operator, a chain of function calls must be
nested, so you read it from the inside out. With |>,
each step appears in the order it actually happens:
Output:
That is the same as ucase$(trim$(full_name$)), read left to
right instead of inside-out. Empty parentheses mean “the piped
value is the only argument”. When the function takes more
arguments, the piped value is the first and the listed ones follow:
Your own routines. A routine that can be called as a
function (one returning parameter) can be a pipe target.
The piped value binds to the routine's first declared
with parameter; defaults fill the rest, and you may still
name the others:
Naming the first parameter as well is a compile error (the pipe already
supplies it), and the target must be a function: piping into an array,
a table, or a routine with no with parameters is rejected.
Longer pipelines. A chain may continue onto the next
line, either by starting the continuation line with |>
(any indentation) or by ending a line with it:
| keeps its traditional
meaning at the end of a print list; it becomes the pipe
only when a > follows immediately. A ! at the
very start of a line is always a comment (so !==== banners
are safe), !> is a comment everywhere — the legacy
header and tail style — and mid-line != means the
same as <>. parse$() returns
|> as a token.
A REAL can hold two special values besides numbers: NaN
("not a number") and infinity, written
_nan, _inf and -_inf. They are
values you put in — a constant, val("NaN"),
a CSV cell that reads Inf, a float field read from a table
— and once present they travel through arithmetic by the IEEE 754
rules: anything with a NaN in it is NaN, _inf + 1 is
_inf, _inf - _inf is NaN, 1 / _inf
is 0. What Sheerpower does not do is manufacture them from
ordinary numbers: 1 / 0 still raises DIVBY0,
sqrt(-1) still raises, and an INTEGER can never hold one
(NUMOVER). So a NaN in your data is always something that
was put there, never a division that went wrong behind your back.
When the IEEE answer is the one you want, ask for it by name:
div0inf(a, b) is the division that gives Inf
or -Inf for a nonzero number over zero and NaN for
0 / 0, and the ordinary exact quotient otherwise — the
companion of div0(a, b), which gives 0. Because it is a
function, a reader can see exactly where an infinity may be born.
The comparison rule is the one to remember: a NaN is equal to nothing,
itself included, so if x = missing then is never true when
both hold a NaN, and x <> missing is always true. The
test that works is isnan(x), and the mask that works is
isnan(v): v(isnan(v)) = 999 fills the holes,
v(v = _nan) = 999 would change nothing. Writing the literal
_nan on either side of = <> < <= > >=
is therefore a compile error that names isnan();
the one place the literal belongs in a test is select case,
where case _nan classifies a NaN. Sorting puts NaN after
everything, including infinity, and treats every NaN as one value, so
sort(), unique() and isin() all
behave; every stats$ function propagates a NaN, and the
array page shows how filter(v, isfinite(v)) skips them. They
print as NaN, Inf and -Inf (sprintf$
honours a width, ignores a precision), and json$ writes
null.
A REAL can also hold a complex number — a real part and an
imaginary part, each carried to 30 significant digits. There is nothing
to declare: write the imaginary unit as a suffix on a number,
4i, and 3 + 4i is the complex number 3 + 4i in
any real variable, array element or cluster field. A real beside a
complex is promoted (2 * z), and a value that is complex
stays complex — z - 4i is 3+0i, never 3
— so real(z) and imag(z) are the way
back to ordinary numbers. The four arithmetic operators compute every
product exactly and round each part once, so (1 + 2i) / (3 + 4i)
is exactly 0.44+0.08i; abs(z) is the magnitude
(a correctly rounded hypotenuse), conj(z) flips the sign of
the imaginary part, arg(z) is the angle in radians, and
complex(re, im) builds one from computed parts.
Two things a complex number does not have. It has no order:
z < w raises NOORDER at run time ("complex
values have no order — compare abs(), real() or imag()"), as do
max, min and clamp, and an
ordering written against a complex literal is a compile error.
And it has no integer value: int, floor,
ceil and round raise NUMOVER, like
NaN. The functions do work: sqr, exp,
log, the trig family and a non-integer power take a complex
(the Processing Complex Numbers page shows them), and signed zeros are
kept and shown (conj(-4 + 0i) prints -4-0i)
because the branch cuts of those functions hinge on them.
json$ writes a complex as the string "3+4i",
and val() reads it back.
|>, which
lets a chain of function calls read in the order it happens, the
IEEE special values NaN and infinity, and complex numbers, which any
REAL can hold.
3 + 4i); + - * /
and a whole-number ^ work on it, = and <> compare both parts, and
the orderings raise NOORDER.
|
Hide Description
|
|
|
Enter or modify the code below, and then click on RUN |
|
Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use. |