by Anand | tags: [ shell bash arithmetic mathematics quadratic equation programming ]
Exploring the Bash Shell - Arithmetic Functions
If you are a programmer using linux
or one of the Unix like operating systems such as Mac OS X or the BSD variants, you will be using the console
or the shell
on a daily basis to run commands.
As programmers, we typically prefer programming languages to run our calculations and to write code. However, one of the most popular (and usually the default) shells on *nix systems is a powerful programming language of its own. We are talking about the bash
shell here.
In this post, the first of a series of posts on shell programming, we will start our exploration of the bash shell by taking a look at one of the most basic capabilities of a programming language - its arithmetic functions.
Bash Shell Arithmetic
Bash supports all the basic arithmetic operators including the modulo operator and supporting an exponent operator in addition.
Defining variables
A variable can be defined on the shell by assigning a value to it.
Examples:
$ x = 10
$ y = 2
Performing Arithmetic
Arithmetic operations can be performed using the following syntax.
$ $(( <expression> ))
Let us look at some examples using the above defined variables.
Addition
$ echo $(( x + y ))
12
Subtraction
$ echo $(( x - y ))
8
Multiplication
$ echo $(( x * y ))
20
Division
$ echo $(( x / y ))
5
Exponentiation
$ echo $(( x ** y ))
100
Modulo
$ echo $(( x % y ))
0
We can use numbers directly as well without needing variables.
$ echo $(( 10 % 3 ))
1
Variable Assignment
The result of an arithmetic operation can be assigned to another shell variable, just like any other shell variable.
$ z=$(( x * y ))
echo $z
20
When performing such assignment, make sure there are no extra spaces after the =
operator on the right. Otherwise you will get an error like the following, as the shell will interpret the value as a command.
$z= $(( x * y))
20: command not found
Complex Operations
The shell can support complex arithmetic with the help of its built-in arithmetic operators and taking some help from additional programs.
Let’s calculate the value of the following quadratic polynomial
$$ax^2 + bx + c$$
for different values of the co-efficients, with varying values of x
.
Shell Functions
The bash shell supports writing of functions. A function is defined using the function
keyword.
function hello
{
echo "hello world";
}
You can define the funcion inline in the shell. However a more common convention is to put the function inside a shell script
typically ending with .sh
extension.
Once defined, you can call the function as if it were a command, on the shell.
$ hello
hello world
Shell functions don’t accept arguments explicitly. Instead arguments are received by the $n
notation. So $1
is the first argument, $2
the second and so on. $*
is a wild-card for receiving all arguments as a single string. Arguments are seprated by spaces.
A Quadratic Polynomial Function
With the above background, let us write a shell function which will calcualte the value of our quadratic polynomial above. It will accept the value of a
,b
,c
,d
and x
as its arguments in that order.
function qpolynomial()
{
# A polynomial function calcualting
# the value of a*x*x + b*x + c
# Pass arguments in the order a,b,c and x
a=$1;b=$2;c=$3;x=$4
echo "Polynomial is $a*x*x + $b*x + $c"
local y=$((a*x*x + b*x + c))
echo "Value for {x=$x} is $y"
}
Note: The `local` keyword creates the variable `y` in the local scope
We can run this on the shell like a command, configuring it with different polynomials and values for x
.
Calculate $$y=10x^2 + 5x + 2, x=1$$
$ qpolynomial 10 5 2 1
Polynomial is 10*x*x + 5*x + 2
Value for {x=1} is 17
Calculate $$y=5x^2 - 8x + 20, x=2$$
$ qpolynomial 5 -8 20 2
Polynomial is 5*x*x + -8*x + 20
Value for {x=2} is 24
Roots of a Quadratic Equation
Now that we’ve dipped our toes into the waters of the shell
, let us plunge a bit more. We will develop a function which calculates the roots of a quadratic equation of the form,
$$ax^2 + bx + c = 0$$
Using the solution,
$$\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$
The function will accept the co-efficients a
,b
and c
as arguments.
Here is the code.
function quadratic_solver()
{
# Receive the co-efficients as 3 arguments
a=$1;b=$2;c=$3
echo "Solving the equation {${a}*x*x + ${b}*x + ${c} = 0}"
# Calculate b*b - 4*a*c as 'y'
local y=$((b*b - 4*a*c))
# Calculate its square root using bc
yroot=`echo "scale=0; sqrt($y)" | bc`
# Calculate root 1
local r1=$(((-1*b + yroot)/(2*a)))
# Calculate root 2
local r2=$(((-1*b - yroot)/(2*a)))
echo "Roots are ($r1, $r2)"
}
Here we are using the shell program bc
which is a precision calculator for calculating, $$\sqrt{b^2 - 4ac}$$
The reason is that the shell exponentiation operator cannot perform fractional exponents and we need a square-root here which is same as raising to 0.5.
Running the Solver
Solving the equation $$x^2 -6x + 9 = 0$$
$ quadratic_solver 1 -6 9
Solving the equation {1*x*x + -6*x + 9 = 0}
Roots are (3, 3)
Solving the equation $$x^2 -7x + 12 = 0$$
$ quadratic_solver 1 -7 12
Solving the equation {1*x*x + -7*x + 12 = 0}
Roots are (4, 3)
Solving the equation $$x^2 -5x - 36 = 0$$
$ quadratic_solver 1 -5 -36
Solving the equation {1*x*x + -5*x + -36 = 0}
Roots are (9, -4)
Caveat and Further Steps
Our simple shell program will work only with quadratic equations having integer solutions as shell cannot do fractional division.
For example, the solution of $$3x^2 + 7x - 6 = 0$$ are
$$ x = (\frac{2}{3}, -3)$$
However our program calculates it as,
$ quadratic_solver 3 7 -6
Solving the equation {3*x*x + 7*x + -6 = 0}
Roots are (0, -3)
This can be fixed easily by performing the division itself using bc
or by printing the fraction as string expression in shell directly if we find the division does not yield a whole integer. This is left as an exercise to the reader.
Hope you enjoyed this post and learned something new about the bash shell. We will have more such posts in the future. If you liked this post, please share your comments after trying it. Have fun!
Note that name and e-mail are required for posting comments