How to use arithmetic operations in bash

Last updated on February 24, 2021 by Dan Nanni

When you are writing a bash script, sometimes you may want to crunch numbers quickly inside the script. For example, you want to convert a unit of data you are working with, round a divided value to the nearest integer, increment a counter in simple loops, etc. Every programming language has built-in support for basic arithmetic operations against common data types. However, since bash is not a general-purpose programming language, but rather a command-line interpreter, it comes with limited support for arithmetic operations.

In this tutorial, I present tips on how to perform integer or floating point arithmetic operations in a bash shell script.

Limitation of Bash for Arithmetic Operations

Variables in bash are not strongly-typed. By default all bash variables are character strings, unless specified with declare. To support arithmetic operations on such string variables, bash treats variables as integers if dicated by execution context. To be more specific, if you are applying arithmetic/comparison operators to the variables that contain only digits, bash automatically treats the variables as integers. Such automatic string-to-integer conversion allows bash to evaluate integer arithmetic. However, bash does not support floating point calculation natively, and you will need to rely on external tools such as GNU bc for floating point operations.

Method One: Arithmetic Evaluation in Bash

While there are multiple ways to perform integer arithmetic in bash, it is recommended, for portability of your script, to use bash's built-in mechanism rather than relying on any external command. Bash's built-in support for integer arithmetic is called arithmetic evaluation. In a nutshell, if you want to perform integer arithmetic using arithmetic evaluation, all you have to do is to surround an arithmetic expression with double parentheses as follows. The format of an arithmetic expression contained in the parentheses is based on the C programming language.

(( arithmetic-expression ))

Check out the examples of how you can express integer arithmetic using arithmetic evalution in bash.

# Integer variables can be stored with or without quote
a=100
b="3"

(( sum = a + b ))    # addition
(( sub = a - b ))    # subtraction
(( mul = a * b ))    # multiplication
(( div = a / b ))    # division
(( mod = a % b ))    # modulo (remainder)
(( exp = a ** b ))   # exponentiation

echo "sum: $sum, sub: $sub, mul: $mul, div: $div, mod: $mod, exp: $exp"

As expected, you will see the following output.

sum: 103, sub: 97, mul: 300, div: 33, mod: 1, exp: 1000000

Note that since bash does not support floating point data type, division of two variables will always produce an integer result by truncation toward zero.

Using arithmetic evaluation, you can also increment or decrement integer variables in bash.

a=100
(( a++ ))
echo "a = $a"
(( a-= 10 ))
echo "a = $a"
a = 101
a = 91

It's also possible to evaluate multiple arithmetic operations within a single expression.

(( form1 = a + b * 100, form2 = a * 100 + b * 2 ))

In arithmetic evaluation, if you are trying to use floating point numbers, you will see "syntax error: invalid arithmetic operator" error.

Method Two: Arithmetic Expansion in Bash

A slightly different built-in mechanism for integer arithmetic in bash is arithmetic expansion. In this case, the output of the arithmetic expression substitutes the expression itself and can be assigned to anther variable.

$(( arithmetic-expression ))
a=100
b="3"

sum=$(( a + b ))
sub=$(( a - b ))

Method Three: Built-in let Command

Another way to perform integer arithmetic natively in bash is to use a built-in command called let, which can evaluate a supplied arithmetic expression.

a=100
b="3"

let sum=a+b   # there shouldn't be any space before/after assignment
let sub=a-b
let mod=a%b
let mod=a%b

You can also perform multiple arithmetic operations in a single let statement.

# Both statements are possible
let 'tmp=a' 'a=b+1' 'b=tmp+1'   
let 'tmp=a, a=b+1, b=tmp+1' 

Method Four: expr Command

You can also perform integer calculation in bash by using the expr command. Unlike let, which is bash's built-in command, expr is an external command line utility that can evaluate an integer expression. Since it is part of GNU Coreutils, using expr in your script does not affect the portability of the script.

a=100
b="3"

# there must be spaces before/after the operator
sum=`expr $a + $b`
sub=`expr $a - $b`
mul=`expr $a \* $b`
div=`expr $a / $b`
mod=`expr $a % $b`

The arithmetic operations supported by expr are addition (+), subtraction (-), multiplication (*), division (/) and modulo (%). Note that multiplication operator must be escaped with '\' as '*' has a built-in meaning of all files in the current directory.

Method Five: bc Command (for Floating Point Arithmetic)

As clarified in the beginning, bash does not support floating point arithmetic natively. In case your bash script does require floating point math, one way to get around the bash's limitation is to invoke an external tool that can deal with floating point arithmetic. One such tool is GNU bc. Unless you are working with a minimal container environment, the bc command should come pre-installed on all modern Linux distributions.

See the example below that runs floating point arithmetic using the bc tool. You need to use echo to pass floating point numbers to bc.

a=12.5
b=5.8

# there must be spaces before/after the operator
sum=`echo "$a + $b" | bc`
mul=`echo "$a * $b" | bc`
div=`echo "scale=2; $a / $b" | bc`

echo "sum: $sum, mul: $mul, div: $div"

In bc, you can adjust the precision of floating point numbers by changing a special variable called scale. So for example, the output of the following floating point division will include two decimal digits after the decimal point.

div=`echo "scale=2; $a / $b" | bc`

The output of the example script looks like the following.

sum: 18.3, mul: 72.5, div: 2.15

If you find this tutorial helpful, I recommend you check out the series of bash shell scripting tutorials provided by Xmodulo.

Support Xmodulo

This website is made possible by minimal ads and your gracious donation via PayPal (Credit Card) or Bitcoin (1M161JGAkz3oaHNvTiPFjNYkeABox8rb4g).

Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.

Xmodulo © 2021 ‒ AboutWrite for UsFeed ‒ Powered by DigitalOcean