Skip to content
shellmap

letDo shell arithmetic in bash, zsh, fish, PowerShell, and cmd across all 5 shells

Equivalents in every shell

Bashunix
let "x = y * 2"

bash builtin. Evaluates each argument as an arithmetic expression; the LAST argument's value becomes the exit status (0 if non-zero, 1 if zero — surprising but standard). Modern bash prefers `(( x = y * 2 ))` (no `let`, double-parens) — same effect, no quoting hell. Operators: `+ - * / % ** ++ -- == != < > <= >= && || << >>`. Integer-only — no floating point.

Zshunix
let "x = y * 2"

zsh builtin, same semantics. `(( x = y * 2 ))` is the recommended modern form. zsh additionally provides `float` and `typeset -F` for floating-point arithmetic — `let` itself remains integer-only.

Fishunix
set x (math "$y * 2")

fish has NO `let` — its arithmetic primitive is `math`, an external command (since fish 3.0 implemented in C; earlier versions used `bc`). `math "1.5 + 2"` supports floating point natively (unlike bash `let`). `set x (math "$y * 2")` captures result into a variable.

PowerShellwindows
$x = $y * 2

pwsh has NO `let` because arithmetic is a first-class language feature — direct assignment with `$x = $y * 2` Just Works for `[int]`, `[double]`, `[decimal]`, `[BigInt]`. Type-cast for explicit precision: `[double]$x = $y / 3.0` forces floating-point even with integer operands. No quoting needed.

cmd.exewindows
set /a x=y*2

`set /a` is cmd's arithmetic. Integer-only, 32-bit signed wrap-around at `0x7FFFFFFF`. Operators similar to bash + cmd-specifics: `+ - * / % () ~ ! & ^ | && || << >> *= /= %= +=`. Quoting differs from bash — variables are NOT prefixed with `$`: `set /a x=y*2` reads `y` automatically. Use `set /a x=%y%*2` to embed a literal value.

Worked examples

Increment a counter

Bash
let i++  # or: (( i++ ))
Fish
set i (math $i + 1)
PowerShell
$i++
cmd.exe
set /a i+=1

Compute a value with mixed multiplication and addition

Bash
(( total = base + items * unit_price ))
Fish
set total (math "$base + $items * $unit_price")
PowerShell
$total = $base + $items * $unit_price
cmd.exe
set /a total=base+items*unit_price

Floating-point math (where shells differ)

Bash
result=$(echo "scale=2; 1.5 * 3" | bc)
Fish
set result (math --scale=2 "1.5 * 3")
PowerShell
$result = [math]::Round(1.5 * 3, 2)

Gotchas

  • bash `let` exit status is BACKWARDS from intuition — `let "x = 0"` returns exit status 1 (because the value is zero); `let "x = 5"` returns 0. Scripts that chain `let && command` are mostly checking for non-zero results, which works by accident. Use `(( ))` for cleaner intent.
  • bash `let` is integer-only. `let "x = 3 / 2"` is `1`, not `1.5`. For floating-point, pipe to `bc` (POSIX), `awk` (universal), or use Python/Perl one-liners. Modern bash 5.2+ does NOT add float support — this is a permanent limitation.
  • fish `math` defaults to `--scale=6` (6 decimal places). `math "1/3"` returns `0.333333`, not `0`. To force integer-like behavior, `math "floor(1/3)"` or `math --scale=0 "1/3"`. The difference from bash's integer-only `let` trips up bash-to-fish ports.
  • cmd `set /a` truncates to 32-bit signed — `set /a x=2147483647+1` becomes `-2147483648` (silent overflow, no error). For 64-bit math in cmd, shell out to PowerShell: `for /f %i in ('powershell -NoProfile -c "[long]2147483647+1"') do @set x=%i`.
  • pwsh integer division: `10 / 3` returns `3.333…` (`[double]`), NOT `3` (no truncation). To get integer division: `[math]::Floor(10 / 3)` or `[int](10 / 3)` (`[int]` cast also ROUNDS to nearest even, banker's rounding — surprising for those expecting truncation). For C-style truncation use `[int][math]::Truncate(10 / 3)`.

WSL & PowerShell Core notes

pwshpwsh's native arithmetic works identically on Windows / Linux / macOS. No `let` needed; `$x = $y * 2` is the cross-OS idiom. Integer-vs-double rules are .NET-driven and OS-independent.
WSLWSL bash `let` / `(( ))` are identical to native Linux. Cross-shell arithmetic from cmd: `for /f %i in ('wsl.exe -e bash -c "echo $((1+2))"') do @echo %i` — WSL bash computes, cmd captures. Floating-point in cmd: shell out to WSL or pwsh as shown above.

Related commands