mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
428 lines
10 KiB
Plaintext
428 lines
10 KiB
Plaintext
Unexpected
|
|
|
|
While calc is C-like, users of C will find some unexpected
|
|
surprises in calc syntax and usage. Persons familiar with C should
|
|
review this file.
|
|
|
|
Persons familiar with shell scripting may want to review this file
|
|
as well, particularly notes dealing with command line evaluation
|
|
and execution.
|
|
|
|
|
|
The Comma
|
|
=========
|
|
|
|
The comma is also used for continuation of obj and mat creation
|
|
expressions and for separation of expressions to be used for
|
|
arguments or values in function calls or initialization lists. The
|
|
precedence order of these different uses is: continuation,
|
|
separator, comma operator. For example, assuming the variables a,
|
|
b, c, d, e, and object type xx have been defined, the arguments
|
|
passed to f in:
|
|
|
|
f(a, b, c, obj xx d, e)
|
|
|
|
are a, b, c, and e, with e having the value of a newly created xx
|
|
object. In:
|
|
|
|
f((a, b), c, (obj xx d), e)
|
|
|
|
the arguments of f are b, c, d, e, with only d being a newly
|
|
created xx object.
|
|
|
|
In combination with other operators, the continuation use of the
|
|
comma has the same precedence as [] and ., the separator use the
|
|
same as the comma operator. For example, assuming xx.mul() has
|
|
been defined:
|
|
|
|
f(a = b, obj xx c, d = {1,2} * obj xx e = {3,4})
|
|
|
|
passes two arguments: a (with value b) and the product d * e of two
|
|
initialized xx objects.
|
|
|
|
|
|
^ is not xor
|
|
** is exponentiation
|
|
====================
|
|
|
|
In C, ^ is the xor operator. The expression:
|
|
|
|
a ^ b
|
|
|
|
yields "a to the b power", NOT "a xor b".
|
|
|
|
Unlike in C, calc evaluates the expression:
|
|
|
|
a ** b
|
|
|
|
also yields "a to the b power".
|
|
|
|
Here "a" and "b" can be a real value or a complex value:
|
|
|
|
2^3 3i^4
|
|
2.5 ^ 3.5 0.5i ^ 0.25
|
|
2.5 ^ 2.718i 3.13145i ^ 0.30103i
|
|
|
|
In addition, "a" can be matrix. In this case "b" must be an integer:
|
|
|
|
mat a[2,2] = {1,2,3,4};
|
|
a^3
|
|
|
|
Note that 'a' == 0 and 'b' is real, then is must be >= 0 as well.
|
|
Also 0^0 and 0**0 return the value 1.
|
|
|
|
Be careful about the precedence of operators. Note that:
|
|
|
|
-1 ^ 0.5 == -1
|
|
|
|
whereas:
|
|
|
|
(-1) ^ 0.5 == 1i
|
|
|
|
because the above expression in parsed as:
|
|
|
|
-(1 ^ 0.5) == -1
|
|
|
|
whereas:
|
|
|
|
(-1) ^ 0.5 == 1i
|
|
|
|
|
|
op= operators associate left to right
|
|
=====================================
|
|
|
|
Operator-with-assignments:
|
|
|
|
+= -= *= /= %= //= &= |= <<= >>= ^= **=
|
|
|
|
associate from left to right instead of right to left as in C.
|
|
For example:
|
|
|
|
a += b *= c
|
|
|
|
has the effect of:
|
|
|
|
a = (a + b) * c
|
|
|
|
where only 'a' is required to be an lvalue. For the effect of:
|
|
|
|
b *= c; a += b
|
|
|
|
when both 'a' and 'b' are lvalues, use:
|
|
|
|
a += (b *= c)
|
|
|
|
|
|
|| yields values other than 0 or 1
|
|
==================================
|
|
|
|
In C:
|
|
|
|
a || b
|
|
|
|
will produce 0 or 1 depending on the logical evaluation
|
|
of the expression. In calc, this expression will produce
|
|
either 'a' or 'b' and is equivalent to the expression:
|
|
|
|
a ? a : b
|
|
|
|
In other words, if 'a' is true, then 'a' is returned, otherwise
|
|
'b' is returned.
|
|
|
|
|
|
&& yields values other than 0 or 1
|
|
==================================
|
|
|
|
In C:
|
|
|
|
a && b
|
|
|
|
will produce 0 or 1 depending on the logical evaluation
|
|
of the expression. In calc, this expression will produce
|
|
either 'a' or 'b' and is equivalent to the expression:
|
|
|
|
a ? b : a
|
|
|
|
In other words, if 'a' is true, then 'b' is returned, otherwise
|
|
'a' is returned.
|
|
|
|
|
|
/ is fractional divide, // is integral divide
|
|
=============================================
|
|
|
|
In C:
|
|
|
|
x/y
|
|
|
|
performs integer division when 'x' and 'y' are integer types.
|
|
In calc, this expression yields a rational number.
|
|
|
|
Calc uses:
|
|
|
|
x//y
|
|
|
|
to perform division with integer truncation and is the equivalent to:
|
|
|
|
int(x/y)
|
|
|
|
|
|
| and & have higher precedence than ==, +, -, *, / and %
|
|
========================================================
|
|
|
|
Is C:
|
|
|
|
a == b | c * d
|
|
|
|
is interpreted as:
|
|
|
|
(a == b) | (c * d)
|
|
|
|
and calc it is interpreted as:
|
|
|
|
a == ((b | c) * d)
|
|
|
|
|
|
calc always evaluates terms from left to right
|
|
==============================================
|
|
|
|
Calc has a definite order for evaluation of terms (addends in a
|
|
sum, factors in a product, arguments for a function or a matrix,
|
|
etc.). This order is always from left to right. but skipping of
|
|
terms may occur for ||, && and ? : .
|
|
|
|
Consider, for example:
|
|
|
|
A * B + C * D
|
|
|
|
In calc above expression is evaluated in the following order:
|
|
|
|
A
|
|
B
|
|
A * B
|
|
C
|
|
D
|
|
C * D
|
|
A * B + C * D
|
|
|
|
This order of evaluation is significant if evaluation of a
|
|
term changes a variable on which a later term depends. For example:
|
|
|
|
x++ * x++ + x++ * x++
|
|
|
|
in calc returns the value:
|
|
|
|
x * (x + 1) + (x + 2) * (x + 3)
|
|
|
|
and increments x as if by x += 4. Similarly, for functions f, g,
|
|
the expression:
|
|
|
|
f(x++, x++) + g(x++)
|
|
|
|
evaluates to:
|
|
|
|
f(x, x + 1) + g(x + 2)
|
|
|
|
and increments x three times.
|
|
|
|
In an other example, this expression:
|
|
|
|
1<<8/2
|
|
|
|
evalues to 128, not 16, because <<8 is performed before the /2.
|
|
|
|
|
|
&A[0] and A are different things in calc
|
|
========================================
|
|
|
|
In calc, value of &A[0] is the address of the first element, whereas
|
|
A is the entire array.
|
|
|
|
|
|
*X may be used to to return the value of X
|
|
==========================================
|
|
|
|
If the current value of a variable X is an octet, number or string,
|
|
*X may be used to to return the value of X; in effect X is an
|
|
address and *X is the value at X.
|
|
|
|
|
|
freeing a variable has the effect of assigning the null value to it
|
|
===================================================================
|
|
|
|
The freeglobals(), freestatics(), freeredc() and free() free
|
|
builtins to not "undefine" the variables, but have the effect of
|
|
assigning the null value to them, and so frees the memory used for
|
|
elements of a list, matrix or object.
|
|
|
|
Along the same lines:
|
|
|
|
undefine *
|
|
|
|
undefines all current user-defined functions. After executing
|
|
all the above freeing functions (and if necessary free(.) to free
|
|
the current "old value"), the only remaining numbers as displayed by
|
|
|
|
show numbers
|
|
|
|
should be those associated with epsilon(), and if it has been
|
|
called, qpi().
|
|
|
|
|
|
#! is also a comment
|
|
====================
|
|
|
|
In addition to the C style /* comment lines */, lines that begin with
|
|
#! are treated as comments.
|
|
|
|
A single # is an calc operator, not a comment. However two or more
|
|
##'s in a row is a comment. See "help pound" for more information.
|
|
|
|
#!/usr/local/src/bin/calc/calc -q -f
|
|
|
|
/* a correct comment */
|
|
## another correct comment
|
|
### two or more together is also a comment
|
|
/*
|
|
* another correct comment
|
|
*/
|
|
print "2+2 =", 2+2; ## yet another comment
|
|
|
|
This next example is WRONG:
|
|
|
|
#!/usr/local/src/bin/calc/calc -q -f
|
|
|
|
# This is not a calc calc comment because it has only a single #
|
|
# You must to start comments with ## or /*
|
|
print "This example has invalid comments"
|
|
|
|
See "help cscript" and "help usage" for more information.
|
|
|
|
|
|
The { must be on the same line as an if, for, while or do
|
|
=========================================================
|
|
|
|
When statement is of the form { ... }, the leading { MUST BE ON
|
|
THE SAME LINE as the if, for, while or do keyword.
|
|
|
|
This works as expected:
|
|
|
|
if (expr) {
|
|
...
|
|
}
|
|
|
|
However this WILL NOT WORK AS EXPECTED:
|
|
|
|
if (expr)
|
|
{
|
|
...
|
|
}
|
|
|
|
because calc will parse the if being terminated by
|
|
an empty statement followed by { ... }. As in:
|
|
|
|
if (expr) ;
|
|
{
|
|
...
|
|
}
|
|
|
|
In the same way, use these forms:
|
|
|
|
for (optionalexpr ; optionalexpr ; optionalexpr) {
|
|
...
|
|
}
|
|
|
|
while (expr) {
|
|
...
|
|
}
|
|
|
|
do {
|
|
...
|
|
while (expr);
|
|
|
|
where the initial { is on the SAME LINE as the if, while,
|
|
for or do keyword.
|
|
|
|
NOTE: See "help statement", "help todo", and "help bugs".
|
|
|
|
|
|
Shell evaluation of command line arguments
|
|
==========================================
|
|
|
|
In most interactive shells:
|
|
|
|
calc 2 * 3
|
|
|
|
will frequently produce a "Missing operator" error because the '*' is
|
|
evaluated as a "shell glob". To avoid this you must quote or escape
|
|
argument with characters that your interactive shell interprets.
|
|
|
|
For example, bash / ksh / sh shell users should use:
|
|
|
|
calc '2 * 3'
|
|
|
|
or:
|
|
|
|
calc 2 \* 3
|
|
|
|
or some other form of shell meta-character escaping.
|
|
|
|
|
|
Calc reads standard input after processing command line args
|
|
============================================================
|
|
|
|
The shell command:
|
|
|
|
seq 5 | while read i; do calc "($i+3)^2"; done
|
|
|
|
FYI: The command "seq 5" will write 1 through 5 on separate
|
|
lines on standard output, while read i sets $i to
|
|
the value of each line that is read from stdin.
|
|
|
|
will produce:
|
|
|
|
16
|
|
2
|
|
3
|
|
4
|
|
5
|
|
|
|
The reason why the last 4 lines of output are 2 through 5 is
|
|
that after calc evaluates the first line and prints (1+3)^2
|
|
(i.e., 16), calc continues to read stdin and slurps up all
|
|
of the remaining data on the pipe.
|
|
|
|
To avoid this problem, use:
|
|
|
|
seq 5 | while read i; do calc "($i+3)^2" </dev/null; done
|
|
|
|
which produces the expected results:
|
|
|
|
16
|
|
25
|
|
36
|
|
49
|
|
64
|
|
|
|
|
|
## Copyright (C) 1999-2007,2014,2017 Landon Curt Noll
|
|
##
|
|
## Calc is open software; you can redistribute it and/or modify it under
|
|
## the terms of the version 2.1 of the GNU Lesser General Public License
|
|
## as published by the Free Software Foundation.
|
|
##
|
|
## Calc is distributed in the hope that it will be useful, but WITHOUT
|
|
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
## Public License for more details.
|
|
##
|
|
## A copy of version 2.1 of the GNU Lesser General Public License is
|
|
## distributed with calc under the filename COPYING-LGPL. You should have
|
|
## received a copy with calc; if not, write to Free Software Foundation, Inc.
|
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
##
|
|
## Under source code control: 1997/03/21 13:15:18
|
|
## File existed as early as: 1997
|
|
##
|
|
## chongo <was here> /\oo/\ http://www.isthe.com/chongo/
|
|
## Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|