Math in bash: how to use all bash operators (+
, -
, /
, *
, **
, &
, &&
, <<
, etc.), and arithmetic expansion, in bash
Of the 346k visitors to this question thus far, I'd be willing to bet 344.9k of them just want the title of this question answered :
How to use mod operator in bash?
Even I googled "bash modulus" looking for that answer, and landed here. So, now that I've figured it out, let's just jump straight to it:
How to use the modulus (%
) operator in bash
Just do this, for instance:
# 7 mod 4 (answer is 3, but to print the output you must use one of the cmds
# below)
$((7 % 4))
# [PREFERRED: no quotes]
# print the result (double quotes are not required)
echo $((7 % 4))
# print the result (with double quotes if you like)
echo "$((7 % 4))"
Example with variables:
num1="7"
num2="4"
# [PREFERRED: no $ signs nor extraneous quotes] result is 3
echo $((num1 % num2))
# Also ok: with $ signs
echo $(($num1 % $num2))
# Also ok: with $ signs and extra quotes
echo "$(("$num1" % "$num2"))"
Store the result into a variable:
mod=$((num1 % num2))
echo "$mod" # result is 3
The main links to study for these concepts are these, from the official GNU bash user manual:
- Bash Arithmetic Expansion
- Bash Shell Arithmetic
More on bash "arithmetic expansion"
I learned the above from @Mark Longair's answer (although it took me some effort to comprehend it all), and that's where I got the link just below. I then did more research.
The $(( ))
part is called "Arithmetic Expansion", and is described in the official GNU bash
user manual here: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Arithmetic-Expansion.
Basic examples (place echo
in front of each one to see the result print to the screen):
# general form
$((mathematical_expression))
# addition
$((7 + 4)) # 11
# subtraction
$((7 - 4)) # 3
# modulus (remainder)
$((7 % 4)) # 3
# logical AND
$((7 && 4)) # 1
# bitwise AND
$((7 & 4)) # 4
# etc.
# See the full operator list below for more
Double quotes around the arithmetic expansion are not needed. From the manual above (emphasis added):
The expression is treated as if it were within double quotes, but a double quote inside the parentheses is not treated specially. All tokens in the expression undergo parameter and variable expansion, command substitution, and quote removal. The result is treated as the arithmetic expression to be evaluated. Arithmetic expansions may be nested.
For all shell arithmetic operators, see the "Shell Arithmetic" section of the GNU bash manual here: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Arithmetic
You essentially have all of the C language mathematical operators at your disposal. The arithmetic is done "in fixed-width integers with no check for overflow", so if you do echo $((11/10))
or echo $((19/10))
you'll get 1
in both cases since the fractional part is truncated for integers.
From the manual link just above (emphasis added):
Evaluation is done in fixed-width integers with no check for overflow, though division by 0 is trapped and flagged as an error. The operators and their precedence, associativity, and values are the same as in the C language.
Since the arithmetic operators in bash have the same precedence as in C, as it states above, you can also reference the C Operator Precedence from the cppreference community wiki here: https://en.cppreference.com/w/c/language/operator_precedence <-- put that in your toolbag.
They are listed in order of highest to lowest precedence:
id++ id--
- variable post-increment and post-decrement
++id --id
- variable pre-increment and pre-decrement
- +
- unary minus and plus
! ~
- logical and bitwise negation
**
- exponentiation
* / %
- multiplication, division, remainder
+ -
- addition, subtraction
<< >>
- left and right bitwise shifts
<= >= < >
- comparison
== !=
- equality and inequality
&
- bitwise AND
^
- bitwise exclusive OR
|
- bitwise OR
&&
- logical AND
||
- logical OR
expr ? expr : expr
- conditional operator
= *= /= %= += -= <<= >>= &= ^= |=
- assignment
expr1 , expr2
- comma
Using alternate bases in your arithmetic, such as binary (base-2), octal (base-8), and hex (base-16)
To learn about using different bases, such as base-2 (binary), base-8 (octal) or base-16 (hex) with the bash arithmetic operators, read the next couple paragraphs below the "Shell Arithmetic" list above in the manual.
Here are a few quick examples with input numbers which are decimal (base-10), octal (base-8), hex (base-16), and binary (base-2), used in the math:
# hex 0xa (decimal 10) + decimal 5 = decimal 15
echo $((0xa + 5)) # prints `15` (decimal 15)
# OR (same thing)
echo $((16#a + 5)) # prints `15` (decimal 15)
# octal 071 (decimal 57) + hex 0xaa (decimal 170) = decimal 227
echo $((071 + 0xaa)) # prints `227` (decimal 227)
# OR (same thing)
echo $((8#71 + 16#aa)) # prints `227` (decimal 227)
# binary 1011 (decimal 11) + decimal 2 = decimal 13
echo $((2#1011 + 2)) # prints `13` (decimal 13)
# binary 1111 (decimal 15) + binary 11111 (decimal 31) = decimal 46
echo $((2#1111 + 2#11111)) # prints `46` (decimal 46)
To print as hex, use printf "0x%X\n" number
:
# prints `0x2E` (hex 2E, or decimal 46)
printf "0x%X\n" $((2#1111 + 2#11111))
To print as binary, use bc
(see my answer here):
# prints `0b101110` (decimal 46)
printf "0b%s\n" "$(echo "obase=2; $((2#1111 + 2#11111))" | bc)"
See also
- [my answer] How do I use floating-point arithmetic in bash?
- If you need a full floating point library in bash, that you can easily import (source), use my code here: bash/floating_point_math.sh in my eRCaGuy_hello_world repo.
- See also my answer about using Bash libraries here: Detailed example: how do you write, import, use, and test libraries in Bash?