Advanced Zsh: Arithmetic Operations Techniques
What Is Zsh Arithmetic?
Zsh, the Z shell, provides powerful built-in arithmetic capabilities that go far beyond simple integer math. Unlike many other shells, Zsh supports integer arithmetic natively via the $(( ... )) syntax, the (( ... )) compound command, and the let builtin. These constructs allow you to perform calculations without spawning external processes like bc, expr, or awk. This not only speeds up your scripts but also gives you tight integration with the shell’s control flow, variables, and expansions.
Zsh arithmetic is based on C‑style operators and supports integer arithmetic, bitwise operations, base conversion, and—through the optional zsh/mathfunc module—floating‑point operations, trigonometric functions, and random numbers. Understanding these techniques is essential for writing efficient, readable, and maintainable Zsh scripts, especially when dealing with counters, indices, numeric conditionals, or data processing.
Why It Matters
In many shell scripts, developers resort to external commands for math. For example, expr $a + $b or echo $(( a + b )) (the latter is better, but still often misused). Using external commands introduces overhead: every call forks a new process, reads its output, and captures it. For a single calculation this is negligible, but in loops or when processing large datasets, the performance hit becomes significant. Moreover, external tools have quirks: expr requires spaces around operators, bc expects a different syntax, and both lack direct access to shell variables without careful quoting.
Zsh’s built‑in arithmetic solves these problems. It is fast (no process creation), fully integrated with the shell’s variable expansion and quoting rules, and supports a rich set of operators. It also allows you to use arithmetic directly in if statements, while loops, and for loops without needing test or [. Mastering these techniques will make your scripts more robust, faster, and easier to read.
How to Use It
Basic Arithmetic with $(( ... ))
The most common way to perform arithmetic and store the result is the $(( ... )) arithmetic expansion. Inside the double parentheses you can write any C‑style expression. The expression is evaluated, and the result is substituted into the command line.
#!/usr/bin/env zsh
# Simple addition
result=$(( 3 + 5 ))
echo $result # Output: 8
# Using variables
a=10
b=20
sum=$(( a + b ))
echo $sum # Output: 30
# Parentheses for grouping
result=$(( (a + b) * 2 ))
echo $result # Output: 60
Note that inside $(( ... )) you do not need to prefix variables with $. Zsh automatically expands them. However, you can use $ if you wish; it is harmless.
Using (( ... )) for Conditionals and Side Effects
The (( ... )) compound command (without the dollar sign) evaluates an arithmetic expression and returns an exit status: 0 (true) if the result is non‑zero, 1 (false) if zero. This is perfect for if, while, and until conditions. Inside (( ... )) you can also assign variables, increment, and use assignment operators.
# Conditional check
x=5
if (( x > 3 )); then
echo "x is greater than 3" # prints
fi
# While loop with arithmetic
i=0
while (( i < 5 )); do
echo $i
(( i++ ))
done
# Output: 0 1 2 3 4
# Assignment inside (())
(( total = a * b ))
echo $total # Output: 200
This is far more concise than using test or [ with -gt etc., and avoids quoting issues.
Using the let Command
The let builtin is an older, but still fully supported, way to perform arithmetic. It evaluates one or more expressions and can assign results to variables. However, let requires that you not use spaces around the assignment operator, and you must quote the expression if it contains spaces or special characters.
let a=10+5
echo $a # 15
let "b = a * 2"
echo $b # 30
let "c = (b - 5) / 3"
echo $c # 8 (integer division)
# Multiple expressions
let x=1 y=2 z=x+y
echo $z # 3
Today, most Zsh users prefer $(( ... )) or (( ... )) because they are more natural and less error‑prone. let is retained for compatibility with older scripts.
Integer vs Floating Point
By default, Zsh arithmetic works only with integers. Division truncates toward zero. If you need floating‑point numbers, you must load the zsh/mathfunc module. This module provides floating‑point operations, trigonometric functions, random numbers, and more.
# Without mathfunc – integer division
result=$(( 10 / 3 ))
echo $result # 3
# Load mathfunc for floating point
zmodload zsh/mathfunc
result=$(( 10. / 3. )) # use decimal points
echo $result # 3.3333333333333335
# Using variables
a=5.5
b=2.0
c=$(( a / b ))
echo $c # 2.75
When you load zsh/mathfunc, Zsh also enables the float type. You can declare a variable as floating point to ensure it always holds a real number:
zmodload zsh/mathfunc
typeset -F pi=3.14159
echo $(( pi * 2 )) # 6.28318
Base Conversion (Hex, Octal, Binary)
Zsh can interpret numbers in different bases using the base#number syntax. The base can be from 2 to 36. This is extremely useful