mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-19 13:33:52 +01:00
190 lines
8.4 KiB
Plaintext
190 lines
8.4 KiB
Plaintext
texinode(Arithmetic Evaluation)(Conditional Expressions)(Jobs & Signals)(Top)
|
|
chapter(Arithmetic Evaluation)
|
|
ifzman(\
|
|
sect(Arithmetic Evaluation)
|
|
)\
|
|
cindex(arithmetic evaluation)
|
|
cindex(evaluation, arithmetic)
|
|
findex(let, use of)
|
|
The shell can perform integer and floating point arithmetic, either using
|
|
the builtin tt(let), or via a substitution of the form tt($((...))). For
|
|
integers, the shell is usually compiled to use 8-byte precision where this
|
|
is available, otherwise precision is 4 bytes. This can be tested, for
|
|
example, by giving the command `tt(print - $(( 12345678901 )))'; if the
|
|
number appears unchanged, the precision is at least 8 bytes. Floating
|
|
point arithmetic is always double precision.
|
|
|
|
The tt(let) builtin command takes arithmetic expressions as arguments; each
|
|
is evaluated separately. Since many of the arithmetic operators, as well
|
|
as spaces, require quoting, an alternative form is provided: for any
|
|
command which begins with a `tt(LPAR()LPAR())', all the characters until a
|
|
matching `tt(RPAR()RPAR())' are treated as a quoted expression and
|
|
arithmetic expansion performed as for an argument of tt(let). More
|
|
precisely, `tt(LPAR()LPAR())var(...)tt(RPAR()RPAR())' is equivalent to
|
|
`tt(let ")var(...)tt(")'. For example, the following statement
|
|
|
|
example((( val = 2 + 1 )))
|
|
|
|
is equivalent to
|
|
|
|
example(let "val = 2 + 1")
|
|
|
|
both assigning the value 3 to the shell variable tt(foo) and returning a
|
|
zero status.
|
|
|
|
cindex(arithmetic base)
|
|
cindex(bases, in arithmetic)
|
|
Integers can be in bases other than 10.
|
|
A leading `tt(0x)' or `tt(0X)' denotes hexadecimal.
|
|
Integers may also be of the form `var(base)tt(#)var(n)',
|
|
where var(base) is a decimal number between two and thirty-six
|
|
representing the arithmetic base and var(n)
|
|
is a number in that base (for example, `tt(16#ff)' is 255 in hexadecimal).
|
|
The var(base)tt(#) may also be omitted, in which case
|
|
base 10 is used. For backwards compatibility the form
|
|
`tt([)var(base)tt(])var(n)' is also accepted.
|
|
|
|
It is also possible to specify a base to be used for output in the form
|
|
`tt([#)var(base)tt(])', for example `tt([#16])'. This is used when
|
|
outputting arithmetical substitutions or when assigning to scalar
|
|
parameters, but an explicitly defined integer or floating point parameter
|
|
will not be affected. If an integer variable is implicitly defined by an
|
|
arithmetic expression, any base specified in this way will be set as the
|
|
variable's output arithmetic base as if the option `tt(-i) var(base)' to
|
|
the tt(typeset) builtin had been used. The expression has no precedence
|
|
and if it occurs more than once in a mathematical expression, the last
|
|
encountered is used. For clarity it is recommended that it appear at the
|
|
beginning of an expression. As an example:
|
|
|
|
example(typeset -i 16 y
|
|
print $(( [#8] x = 32, y = 32 ))
|
|
print $x $y)
|
|
|
|
outputs first `tt(8#40)', the rightmost value in the given output base, and
|
|
then `tt(8#40 16#20)', because tt(y) has been explicitly declared to
|
|
have output base 16, while tt(x) (assuming it does not already exist) is
|
|
implicitly typed by the arithmetic evaluation, where it acquires the output
|
|
base 8.
|
|
|
|
pindex(C_BASES, use of)
|
|
pindex(OCTAL_ZEROES, use of)
|
|
If the tt(C_BASES) option is set, hexadecimal numbers in the standard C
|
|
format, for example tt(0xFF) instead of the usual `tt(16#FF)'. If the
|
|
option tt(OCTAL_ZEROES) is also set (it is not by default), octal numbers
|
|
will be treated similarly and hence appear as `tt(077)' instead of
|
|
`tt(8#77)'. This option has no effect on the output of bases other than
|
|
hexadecimal and octal, and these formats are always understood on input.
|
|
|
|
When an output base is specified using the `tt([#)var(base)tt(])' syntax,
|
|
an appropriate base prefix will be output if necessary, so that the value
|
|
output is valid syntax for input. If the tt(#) is doubled, for example
|
|
`tt([##16])', then no base prefix is output.
|
|
|
|
Floating point constants are recognized by the presence of a decimal point
|
|
or an exponent. The decimal point may be the first character of the
|
|
constant, but the exponent character tt(e) or tt(E) may not, as it will be
|
|
taken for a parameter name.
|
|
|
|
cindex(arithmetic operators)
|
|
cindex(operators, arithmetic)
|
|
An arithmetic expression uses nearly the same syntax, precedence, and
|
|
associativity of expressions in C.
|
|
The following operators are supported (listed in decreasing order
|
|
of precedence):
|
|
|
|
startsitem()
|
|
sitem(tt(PLUS() - ! ~ PLUS()PLUS() --))(unary plus/minus, logical NOT, complement, {pre,post}{in,de}crement)
|
|
sitem(tt(<< >>))(bitwise shift left, right)
|
|
sitem(tt(&))(bitwise AND)
|
|
sitem(tt(^))(bitwise XOR)
|
|
sitem(tt(|))(bitwise OR)
|
|
sitem(tt(**))(exponentiation)
|
|
sitem(tt(* / %))(multiplication, division, modulus (remainder))
|
|
sitem(tt(PLUS() -))(addition, subtraction)
|
|
sitem(tt(< > <= >=))(comparison)
|
|
sitem(tt(== !=))(equality and inequality)
|
|
sitem(tt(&&))(logical AND)
|
|
sitem(tt(|| ^^))(logical OR, XOR)
|
|
sitem(tt(? :))(ternary operator)
|
|
sitem(tt(= PLUS()= -= *= /= %= &= ^= |= <<= >>= &&= ||= ^^= **=))(assignment)
|
|
sitem(tt(,))(comma operator)
|
|
endsitem()
|
|
|
|
The operators `tt(&&)', `tt(||)', `tt(&&=)', and `tt(||=)' are
|
|
short-circuiting, and only one of the latter two expressions in a ternary
|
|
operator is evaluated. Note the precedence of the bitwise AND, OR,
|
|
and XOR operators.
|
|
|
|
cindex(mathematical functions, use of)
|
|
cindex(functions, math, use of)
|
|
Mathematical functions can be called with the syntax
|
|
`var(func)tt(LPAR())var(args)tt(RPAR())', where the function decides
|
|
if the var(args) is used as a string or a comma-separated list of
|
|
arithmetic expressions. The shell currently defines no mathematical
|
|
functions by default, but the module tt(zsh/mathfunc) may be loaded with
|
|
the tt(zmodload) builtin to provide standard floating point mathematical
|
|
functions.
|
|
|
|
An expression of the form `tt(##)var(x)' where var(x) is any character
|
|
sequence such as `tt(a)', `tt(^A)', or `tt(\M-\C-x)' gives the ASCII
|
|
value of this character and an expression of the form `tt(#)var(foo)'
|
|
gives the ASCII value of the first character of the value of the
|
|
parameter var(foo). Note that this is different from the expression
|
|
`tt($#)var(foo)', a standard parameter substitution which gives the
|
|
length of the parameter var(foo). `tt(#\)' is accepted instead of
|
|
`tt(##)', but its use is deprecated.
|
|
|
|
Named parameters and subscripted arrays can be referenced by name within an
|
|
arithmetic expression without using the parameter expansion syntax. For
|
|
example,
|
|
|
|
example(((val2 = val1 * 2)))
|
|
|
|
assigns twice the value of tt($val1) to the parameter named tt(val2).
|
|
|
|
An internal integer representation of a named parameter
|
|
can be specified with the tt(integer) builtin.
|
|
cindex(parameters, integer)
|
|
cindex(integer parameters)
|
|
findex(integer, use of)
|
|
Arithmetic evaluation is performed on the value of each
|
|
assignment to a named parameter declared integer
|
|
in this manner. Assigning a floating point number to an integer results in
|
|
rounding down to the next integer.
|
|
|
|
cindex(parameters, floating point)
|
|
cindex(floating point parameters)
|
|
findex(float, use of)
|
|
Likewise, floating point numbers can be declared with the tt(float)
|
|
builtin; there are two types, differing only in their output format, as
|
|
described for the tt(typeset) builtin. The output format can be bypassed
|
|
by using arithmetic substitution instead of the parameter substitution,
|
|
i.e. `tt(${)var(float)tt(})' uses the defined format, but
|
|
`tt($LPAR()LPAR())var(float)tt(RPAR()RPAR())' uses a generic floating point
|
|
format.
|
|
|
|
Promotion of integer to floating point values is performed where
|
|
necessary. In addition, if any operator which requires an integer
|
|
(`tt(~)', `tt(&)', `tt(|)', `tt(^)', `tt(%)', `tt(<<)', `tt(>>)' and their
|
|
equivalents with assignment) is given a floating point argument, it will be
|
|
silently rounded down to the next integer.
|
|
|
|
Scalar variables can hold integer or floating point values at different
|
|
times; there is no memory of the numeric type in this case.
|
|
|
|
If a variable is first assigned in a numeric context without previously
|
|
being declared, it will be implicitly typed as tt(integer) or tt(float) and
|
|
retain that type either until the type is explicitly changed or until the
|
|
end of the scope. This can have unforeseen consequences. For example, in
|
|
the loop
|
|
|
|
example(for (( f = 0; f < 1; f += 0.1 )); do
|
|
# use $f
|
|
done)
|
|
|
|
if tt(f) has not already been declared, the first assignment will cause it
|
|
to be created as an integer, and consequently the operation `tt(f += 0.1)'
|
|
will always cause the result to be truncated to zero, so that the loop will
|
|
fail. A simple fix would be to turn the initialization into `tt(f = 0.0)'.
|
|
It is therefore best to declare numeric variables with explicit types.
|