diff options
Diffstat (limited to 'Doc/Zsh/arith.yo')
-rw-r--r-- | Doc/Zsh/arith.yo | 123 |
1 files changed, 101 insertions, 22 deletions
diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo index 1560c81d3..e47c0284a 100644 --- a/Doc/Zsh/arith.yo +++ b/Doc/Zsh/arith.yo @@ -5,18 +5,49 @@ sect(Arithmetic Evaluation) )\ cindex(arithmetic evaluation) cindex(evaluation, arithmetic) -An ability to perform integer arithmetic is provided with the builtin tt(let). findex(let, use of) -Evaluations are performed using em(long) arithmetic. +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(bases, in arithmetic) +Integers can be in bases other than 10. A leading `tt(0x)' or `tt(0X)' denotes hexadecimal. -Otherwise, numbers are of the form `[var(base)tt(#)]var(n)', +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). -If var(base) is omitted -then base 10 is used. For backwards compatibility the form +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. +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 @@ -42,18 +73,37 @@ 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, +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. -An expression of the form `tt(#\)var(x)' where var(x) is any character -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). +cindex(math functions) +cindex(functions, math) +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 substitution syntax. +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. @@ -62,12 +112,41 @@ 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. - -Since many of the arithmetic operators require -quoting, an alternative form of the tt(let) command 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. -More precisely, `tt(LPAR()LPAR()) ... tt(RPAR()RPAR())' -is equivalent to `tt(let ")...tt(")'. +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. |