Bash Division Explained

Last updated: March 30, 2023 | Linuxopsys

We cannot divide numbers directly in Bash as they would be treated as strings. However, Bash provides a lot of tools and commands to perform arithmetic division. 

In this tutorial, we are going to learn about different ways to divide with variables. We will also focus on the advantages and limitations of some of the commonly used methods. Furthermore, we will learn how to round the result of division.

Prerequisites

  • A text editor 
  • Access to a terminal

1. Division using let

One of the most common Bash command line tools is let. It accepts one or more arithmetic operations and evaluates them. We can divide the integers stored in shell variables directly using let or make use of variables which are not defined within the context of the let command.

Example:

#!/bin/bash
a=40
b=4
c=30
e=20.2

let q1=$a/$b			#40/4
echo a/b is $q1

let x=10 y=-2 
let q2=$x/$y			#10/-2
echo x/y is $q2

let q3=$c/$b			#30/4
echo c/b is $q3

let q4=$e/$b			#20.2/4
echo e/b is $q4

As we can see from this example, we can either declare variables outside the scope of let or use it with let. Furthermore, from the result we can see that bash truncates the decimal point and the numbers after that. Bash doesn’t support floating-point arithmetic. The other thing to note is that the numerator and the denominator must be integers, they can’t be floating-point numbers.

script output - bash division using let

2. Division using expr

Just like let, we can divide using the expr command line utility. 

Example:

#!/bin/bash
a=40
b=-4
c=30
e=20.2

expr $a / $b			#40/-4

expr $c / $b			#30/-4

expr $e / $b			#20.2/-4

We can directly wrap the expression inside expr to perform division. Furthermore, the result of division, performed using expr, is an integer. Similar to the expr command, the numerator and the denominator cannot be floating point numbers. Spaces are required before and after the division operator. If not provided, the expression supplied to the expr command is processed as a string, giving a syntax error.

script output - bash division using expr

3. Division using double parentheses

Double parentheses compound command $(()) helps to evaluate the expression written inside it. We can write the division to be performed inside these parentheses.

Example:

#!/bin/bash
a=40
b=-4
c=30
e=20.2

echo $(($a/$b))			#40/-4

echo $(($c / $b))			#30/-4

echo $(($e/$b))			#20.2/-4

We can directly divide by having the expression inside the $(()). As we saw in let and expr examples, the result of division, here is an integer too. Similarly, the numerator and the denominator cannot be floating point numbers. The spaces before and after the division operator are not necessary. The limitations about the presence of the spaces for the expr command aren’t valid for double parentheses command.

script output - bash division using double parentheses

4. Division using awk command

The awk command was developed by Aho, Weinberger, and Kernighan and gets its name from their initials. It is a powerful, widely used Linux tool that lets us process and manipulate data.It also supports performing arithmetic operations.

Example:

#!/bin/bash
a=40
b=-4
c=30
e=20.2

awk "BEGIN {print $a/$b}"		#40/-4

awk 'BEGIN {x=10;y=8;print x/y}'	#10/8

awk "BEGIN {print $c/$b}"		#30/-4

awk "BEGIN {print $e/$b}"		#20.2/-4

From this example, we can see how to use awk with the support of the BEGIN keyword to carry out division. We can use the variables already defined in the shell, but we must use double quotes. The other option is to declare variables inside the awk command.

Here, we can also see the quotient, if a decimal number, is not truncated. Unlike all the above examples, the result is a floating point number. The dividend and the divisor variables can be floating point numbers too.

script output - bash division using awk

5. Division using bc command

The bc command stands for Basic Calculator. The bc command can run in interactive mode as well. It is also a helpful tool if you want to perform any arithmetic operation including division. 

Example:

#!/bin/bash

bc			#interactive mode

bc -q 			#interactive mode without welcome

a=40
b=-4
c=30
e=20.2
f=6

echo "$a / $b" | bc 			#40/-4

echo "$c / $b" | bc	 		#30/-4

echo "scale=2; $c / $b" | bc 		#30/-4 till 2 decimal places

echo "scale=4; $c / $f" | bc 		#30/-6 till 4 decimal places

echo "scale=4; $e / $f" | bc 		#20.2/-6 till 4 decimal places

From this example, simply executing the bc command without any parameters runs it in an interactive mode. This command with -q flag suppresses the welcome message. However, shell variables cannot be used in interactive mode.

We can use the variables in non-interactive mode by piping (|) as shown above. The output of the echo command is made available to the bc command by using the pipe.
The keyword "scale" is specific to the bc command and gives us the value in decimals. The value of scale gives us those many numbers to the right of the decimal.

The dividend and the divisors can also be floating-point numbers in this case.  

script output - bash division using bc

6. Division using printf command

The printf command is similar to the printf command used to display the result or the statement on the standard output in the C programming language. In Bash, the inputs needed for the printf are a format specification and arguments. The output is a formatted text displayed on the console.

Syntax:

printf "%.<i>f\n" $((10**<i> * <numerator>/<denominator>))e-<i>

Where i is the precision number. It represents the number of the digits wanted after the decimal point. The default value is 6

Example:

#!/bin/bash

a=50
b=-4
e=20.2
f=6

printf "%f\n" $((a/b))			#50/-4

printf "%f\n" $((a/f))			#50/6 without decimals

printf "%.3f\n" $((10**3 * a/f))e-3 	# 50/6 till 3 decimal places

printf "%f\n" $((e/f))			#error

In this example we can see how to use the printf command. %f\n” is the formatted text printed on the console. The format specifier (%f) prints the corresponding argument as a floating-point number. \n is used for generating a new line. $((a/b)) is the argument made available to the format specifier.

In the second case, the decimal numbers aren’t correct. This is because the output of the expression inside the dollar double parentheses $((a/f)) is an integer. This we have learnt in the above examples. The %f format specifier only printed this integer as a floating-point number, resulting in 8.000000. As the default precision value is 6, we get 6 numbers after the decimal.

In the third case, we are getting a precise number. Bash evaluates the argument, after the format specifier, from left to right. First, 10**3 is calculated as 10 to the power of 3 resulting in 1000. 1000 is then multiplied by $a giving us 50000. After which it is divided by $f, resulting in 8333 as it was an integer division. The argument passed to the format specifier is 8333e-3. This was then handled as a floating-point number, dividing 8333 by 1000, giving the output till 3 decimal places.

The numerator and the denominator have to be integers. Floating point numbers will give a syntax error.

script output - bash division using printf

7. Rounding the result of division

We have 3 ways to round a number. For a number n,

  • Floor rounding – The output is the greatest integer less than or equal to n
  • Ceiling rounding – The result will be the least integer greater than or equal to n
  • Half-up rounding – The half-way values of n are always rounded up

Syntax and examples

ExpressionFloorCeilingHalf up
A/BA/B(A/B) + (A%B>0)(A+B/2)/B
16/4444
21/2101111
100/3333433

Let’s try to implement the same:

#!/bin/bash

echo "Floor rounding of 16/4 = $(( 16 / 4 ))"
echo "Floor rounding of 21/2 = $(( 21 / 2 ))"
echo "Floor rounding of 100/3 = $(( 100 / 3 ))"

echo "Ceiling rounding of 16/4 = $(( ( 16 / 4 ) + ( 16 % 4 > 0 ) ))"
echo "Ceiling rounding of 21/2 = $(( ( 21 / 2 ) + ( 21 % 2 > 0 ) ))"
echo "Ceiling rounding of 100/3 = $(( ( 100 / 3 ) + ( 100 % 3 > 0 ) ))"

echo "Half up rounding of 16/4 = $(( ( 16 + 4 / 2 ) / 4 ))"
echo "Half up rounding of 21/2 = $(( ( 21 + 2 / 2 ) / 2 ))"
echo "Half up rounding of 100/3 = $(( ( 100 + 3 / 2 ) / 3 ))"

In this above example:

  • Floor rounding- Bash performs floor rounding by division automatically.
  • Ceiling rounding- We calculate the remainder of expression. If it is zero, then the result is the number, otherwise it is one greater than the number.
  • Half up rounding- We divide the divisor by 2 and add the result to the dividend. The number obtained is finally divided by the original divisor.
script output - bash rounding

Conclusion

  • There are many ways to perform division in Bash.
  • The command line tools like let and expr and $(()) have limitations and cannot be used to generate floating point numbers.
  • printf can give precise results for division. However, it cannot be used with floating point numbers.
  • awk and bc are widely used tools to perform division and limitations of the above commands can be overcome using these utilities.
  • We learned different techniques of rounding up
SHARE

Comments

Please add comments below to provide the author your ideas, appreciation and feedback.

Leave a Reply

Leave a Comment