377 lines
12 KiB
Markdown
377 lines
12 KiB
Markdown
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||
|
||
- [11 Arithmetic Evaluation](#11-arithmetic-evaluation)
|
||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||
|
||
<span id="Arithmetic-Evaluation"></span>
|
||
<span id="Arithmetic-Evaluation-1"></span>
|
||
|
||
# 11 Arithmetic Evaluation
|
||
|
||
<span id="index-arithmetic-evaluation"></span>
|
||
<span id="index-evaluation_002c-arithmetic"></span>
|
||
<span id="index-let_002c-use-of"></span>
|
||
|
||
The shell can perform integer and floating point arithmetic, either
|
||
using the builtin `let`, or via a substitution of the form
|
||
`$((``...``))`. 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 ‘`print -
|
||
$(( 12345678901 ))`’; if the number appears unchanged, the precision is
|
||
at least 8 bytes. Floating point arithmetic always uses the ‘double’
|
||
type with whatever corresponding precision is provided by the compiler
|
||
and the library.
|
||
|
||
The `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 ‘`((`’, all the characters until a
|
||
matching ‘`))`’ are treated as a quoted expression and arithmetic
|
||
expansion performed as for an argument of `let`. More precisely,
|
||
‘`((``...``))`’ is equivalent to ‘`let "``...``"`’. The return status
|
||
is 0 if the arithmetic value of the expression is non-zero, 1 if it is
|
||
zero, and 2 if an error occurred.
|
||
|
||
For example, the following statement
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
(( val = 2 + 1 ))
|
||
```
|
||
|
||
</div>
|
||
|
||
is equivalent to
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
let "val = 2 + 1"
|
||
```
|
||
|
||
</div>
|
||
|
||
both assigning the value 3 to the shell variable `val` and returning a
|
||
zero status.
|
||
|
||
<span id="index-arithmetic-base"></span>
|
||
<span id="index-bases_002c-in-arithmetic"></span>
|
||
|
||
Integers can be in bases other than 10. A leading ‘`0x`’ or ‘`0X`’
|
||
denotes hexadecimal and a leading ‘`0b`’ or ‘`0B`’ binary. Integers may
|
||
also be of the form ‘`base``#``n`’, where `base` is a decimal number
|
||
between two and thirty-six representing the arithmetic base and `n` is a
|
||
number in that base (for example, ‘`16#ff`’ is 255 in hexadecimal). The
|
||
`base``#` may also be omitted, in which case base 10 is used. For
|
||
backwards compatibility the form ‘`[``base``]``n`’ is also accepted.
|
||
|
||
An integer expression or a base given in the form ‘`base``#``n`’ may
|
||
contain underscores (‘`_`’) after the leading digit for visual guidance;
|
||
these are ignored in computation. Examples are `1_000_000` or
|
||
`0xffff_ffff` which are equivalent to `1000000` and `0xffffffff`
|
||
respectively.
|
||
|
||
It is also possible to specify a base to be used for output in the form
|
||
‘`[#``base``]`’, for example ‘`[#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 ‘`-i` `base`’ to the `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:
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
typeset -i 16 y
|
||
print $(( [#8] x = 32, y = 32 ))
|
||
print $x $y
|
||
```
|
||
|
||
</div>
|
||
|
||
outputs first ‘`8#40`’, the rightmost value in the given output base,
|
||
and then ‘`8#40 16#20`’, because `y` has been explicitly declared to
|
||
have output base 16, while `x` (assuming it does not already exist) is
|
||
implicitly typed by the arithmetic evaluation, where it acquires the
|
||
output base 8.
|
||
|
||
The `base` may be replaced or followed by an underscore, which may
|
||
itself be followed by a positive integer (if it is missing the value 3
|
||
is used). This indicates that underscores should be inserted into the
|
||
output string, grouping the number for visual clarity. The following
|
||
integer specifies the number of digits to group together. For example:
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
setopt cbases
|
||
print $(( [#16_4] 65536 ** 2 ))
|
||
```
|
||
|
||
</div>
|
||
|
||
outputs ‘`0x1_0000_0000`’.
|
||
|
||
The feature can be used with floating point numbers, in which case the
|
||
base must be omitted; grouping is away from the decimal point. For
|
||
example,
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
zmodload zsh/mathfunc
|
||
print $(( [#_] sqrt(1e7) ))
|
||
```
|
||
|
||
</div>
|
||
|
||
outputs ‘`3_162.277_660_168_379_5`’ (the number of decimal places shown
|
||
may vary).
|
||
|
||
<span id="index-C_005fBASES_002c-use-of"></span>
|
||
<span id="index-OCTAL_005fZEROES_002c-use-of"></span>
|
||
|
||
If the `C_BASES` option is set, hexadecimal numbers are output in the
|
||
standard C format, for example ‘`0xFF`’ instead of the usual ‘`16#FF`’.
|
||
If the option `OCTAL_ZEROES` is also set (it is not by default), octal
|
||
numbers will be treated similarly and hence appear as ‘`077`’ instead of
|
||
‘`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 ‘`[#``base``]`’ syntax, an
|
||
appropriate base prefix will be output if necessary, so that the value
|
||
output is valid syntax for input. If the `#` is doubled, for example
|
||
‘`[##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 `e` or `E` may not, as it will
|
||
be taken for a parameter name. All numeric parts (before and after the
|
||
decimal point and in the exponent) may contain underscores after the
|
||
leading digit for visual guidance; these are ignored in computation.
|
||
|
||
<span id="index-arithmetic-operators"></span>
|
||
<span id="index-operators_002c-arithmetic"></span>
|
||
|
||
An arithmetic expression uses nearly the same syntax and associativity
|
||
of expressions as in C.
|
||
|
||
In the native mode of operation, the following operators are supported
|
||
(listed in decreasing order of precedence):
|
||
|
||
- `+ - ! ~ ++ –`
|
||
unary plus/minus, logical NOT, complement, {pre,post}{in,de}crement
|
||
|
||
- `<< >>`
|
||
bitwise shift left, right
|
||
|
||
- `&`
|
||
bitwise AND
|
||
|
||
- `^`
|
||
bitwise XOR
|
||
|
||
- `|`
|
||
bitwise OR
|
||
|
||
- `**`
|
||
exponentiation
|
||
|
||
- `* / %`
|
||
multiplication, division, modulus (remainder)
|
||
|
||
- `+ -`
|
||
addition, subtraction
|
||
|
||
- `< > <= >=`
|
||
comparison
|
||
|
||
- `== !=`
|
||
equality and inequality
|
||
|
||
- `&&`
|
||
logical AND
|
||
|
||
- `|| ^^`
|
||
logical OR, XOR
|
||
|
||
- `? :`
|
||
ternary operator
|
||
|
||
- `= += -= *= /= %= &= ^= |= <<= >>= &&= ||= ^^= **=`
|
||
assignment
|
||
|
||
- `,`
|
||
comma operator
|
||
|
||
The operators ‘`&&`’, ‘`||`’, ‘`&&=`’, and ‘`||=`’ 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.
|
||
|
||
With the option `C_PRECEDENCES` the precedences (but no other
|
||
properties) of the operators are altered to be the same as those in most
|
||
other languages that support the relevant operators:
|
||
|
||
- `+ - ! ~ ++ –`
|
||
unary plus/minus, logical NOT, complement, {pre,post}{in,de}crement
|
||
|
||
- `**`
|
||
exponentiation
|
||
|
||
- `* / %`
|
||
multiplication, division, modulus (remainder)
|
||
|
||
- `+ -`
|
||
addition, subtraction
|
||
|
||
- `<< >>`
|
||
bitwise shift left, right
|
||
|
||
- `< > <= >=`
|
||
comparison
|
||
|
||
- `== !=`
|
||
equality and inequality
|
||
|
||
- `&`
|
||
bitwise AND
|
||
|
||
- `^`
|
||
bitwise XOR
|
||
|
||
- `|`
|
||
bitwise OR
|
||
|
||
- `&&`
|
||
logical AND
|
||
|
||
- `^^`
|
||
logical XOR
|
||
|
||
- `||`
|
||
logical OR
|
||
|
||
- `? :`
|
||
ternary operator
|
||
|
||
- `= += -= *= /= %= &= ^= |= <<= >>= &&= ||= ^^= **=`
|
||
assignment
|
||
|
||
- `,`
|
||
comma operator
|
||
|
||
Note the precedence of exponentiation in both cases is below that of
|
||
unary operators, hence ‘`-3**2`’ evaluates as ‘`9`’, not ‘`-9`’. Use
|
||
parentheses where necessary: ‘`-(3**2)`’. This is for compatibility with
|
||
other shells.
|
||
|
||
<span id="index-mathematical-functions_002c-use-of"></span>
|
||
<span id="index-functions_002c-math_002c-use-of"></span>
|
||
|
||
Mathematical functions can be called with the syntax
|
||
‘`func``(``args``)`’, where the function decides if the `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 `zsh/mathfunc` may be loaded with the `zmodload` builtin to
|
||
provide standard floating point mathematical functions.
|
||
|
||
An expression of the form ‘`##``x`’ where `x` is any character sequence
|
||
such as ‘`a`’, ‘`^A`’, or ‘`\M-\C-x`’ gives the value of this character
|
||
and an expression of the form ‘`#``name`’ gives the value of the first
|
||
character of the contents of the parameter `name`. Character values are
|
||
according to the character set used in the current locale; for multibyte
|
||
character handling the option `MULTIBYTE` must be set. Note that this
|
||
form is different from ‘`$#``name`’, a standard parameter substitution
|
||
which gives the length of the parameter `name`. ‘`#\`’ is accepted
|
||
instead of ‘`##`’, 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,
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
((val2 = val1 * 2))
|
||
```
|
||
|
||
</div>
|
||
|
||
assigns twice the value of `$val1` to the parameter named `val2`.
|
||
|
||
An internal integer representation of a named parameter can be specified
|
||
with the `integer` builtin.
|
||
<span id="index-parameters_002c-integer"></span>
|
||
<span id="index-integer-parameters"></span>
|
||
<span id="index-integer_002c-use-of"></span> 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 towards zero.
|
||
|
||
<span id="index-parameters_002c-floating-point"></span>
|
||
<span id="index-floating-point-parameters"></span>
|
||
<span id="index-float_002c-use-of"></span>
|
||
|
||
Likewise, floating point numbers can be declared with the `float`
|
||
builtin; there are two types, differing only in their output format, as
|
||
described for the `typeset` builtin. The output format can be bypassed
|
||
by using arithmetic substitution instead of the parameter substitution,
|
||
i.e. ‘`${``float``}`’ uses the defined format, but ‘`$((``float``))`’
|
||
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
|
||
(‘`&`’, ‘`|`’, ‘`^`’, ‘`<<`’, ‘`>>`’ and their equivalents with
|
||
assignment) is given a floating point argument, it will be silently
|
||
rounded towards zero except for ‘`~`’ which rounds down.
|
||
|
||
Users should beware that, in common with many other programming
|
||
languages but not software designed for calculation, the evaluation of
|
||
an expression in zsh is taken a term at a time and promotion of integers
|
||
to floating point does not occur in terms only containing integers. A
|
||
typical result of this is that a division such as `6/8` is truncated, in
|
||
this being rounded towards 0. The `FORCE_FLOAT` shell option can be used
|
||
in scripts or functions where floating point evaluation is required
|
||
throughout.
|
||
|
||
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 `integer` or `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
|
||
|
||
<div class="example">
|
||
|
||
``` example
|
||
for (( f = 0; f < 1; f += 0.1 )); do
|
||
# use $f
|
||
done
|
||
```
|
||
|
||
</div>
|
||
|
||
if `f` has not already been declared, the first assignment will cause it
|
||
to be created as an integer, and consequently the operation ‘`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 ‘`f
|
||
= 0.0`’. It is therefore best to declare numeric variables with explicit
|
||
types.
|
||
|
||
-----
|
||
|
||
This document was generated on *February 15, 2020* using
|
||
[*texi2html 5.0*](http://www.nongnu.org/texi2html/).
|
||
Zsh version 5.8, released on February 14, 2020.
|