zsh-manual-mdbook/zsh_manual/src/Arithmetic-Evaluation.md
2021-05-17 10:18:05 -05:00

377 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 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 variables
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.