ZSH 11 Arithmetic Evaluation
ZSH 11 Arithmetic Evaluation
html
11 Arithmetic Evaluation
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 double-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.
is equivalent to
both assigning the value 3 to the shell variable val and returning a zero status.
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:
typeset -i 16 y
print $(( [#8] x = 32, y = 32 ))
print $x $y
outputs first ‘8#40’, the rightmost value in the given output base, and then ‘8#40 16#20’, because y has been
1 de 6 28/9/2023, 21:54
zsh: 11 Arithmetic Evaluation file:///D:/03.estudiar/01.books/zsh_html/Arithmetic-Evaluation.html
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:
setopt cbases
print $(( [#16_4] 65536 ** 2 ))
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,
zmodload zsh/mathfunc
print $(( [#_] sqrt(1e7) ))
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.
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):
+ - ! ~ ++ –
<< >>
&
bitwise AND
2 de 6 28/9/2023, 21:54
zsh: 11 Arithmetic Evaluation file:///D:/03.estudiar/01.books/zsh_html/Arithmetic-Evaluation.html
bitwise XOR
bitwise OR
**
exponentiation
* / %
+ -
addition, subtraction
comparison
== !=
&&
logical AND
|| ^^
? :
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:
+ - ! ~ ++ –
3 de 6 28/9/2023, 21:54
zsh: 11 Arithmetic Evaluation file:///D:/03.estudiar/01.books/zsh_html/Arithmetic-Evaluation.html
**
exponentiation
* / %
+ -
addition, subtraction
<< >>
comparison
== !=
&
bitwise AND
bitwise XOR
bitwise OR
&&
logical AND
^^
logical XOR
||
logical OR
? :
ternary operator
assignment
4 de 6 28/9/2023, 21:54
zsh: 11 Arithmetic Evaluation file:///D:/03.estudiar/01.books/zsh_html/Arithmetic-Evaluation.html
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.
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,
((val2 = val1 * 2))
An internal integer representation of a named parameter can be specified with the integer builtin. 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.
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
for (( f = 0; f < 1; f += 0.1 )); do
5 de 6 28/9/2023, 21:54
zsh: 11 Arithmetic Evaluation file:///D:/03.estudiar/01.books/zsh_html/Arithmetic-Evaluation.html
# use $f
done
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 May 14, 2022 using texi2html 5.0.
Zsh version 5.9, released on May 14, 2022.
6 de 6 28/9/2023, 21:54