Tag Archives: Shell

Explore the Power of the Bench Calculator

This second article of the mathematical journey through open source, takes you through the basics of bench calculator.

<< First Article

Faced with the limitations of the shell command expr and other shell constructs, here we are all set to explore the powerful command bc. bc stands for bench calculator. It is not just a command or tool but a complete language in itself. And its power lies in its arbitrary precision-ness with not only integers but with real number. Wondering what that means? It just means that its computation is mostly not limited by size of the integer or real number types, unlike in most programming languages. Thus, this is more closer to our day to day dealing of mathematics, keeping away the internal details of computer’s precision blah blah. So, let’s get started with the first usual maths. And then we will move onto more involved one with variables, conditionals, and later on with functions and recursion.

Basic operations

For integer-only math, you may invoke the bench calculator as bc. For a full-fledged real number math, you may invoke it as bc -l. Once invoked, it will print a welcome message and then wait for you to just type your math statements and press Enter to get your answer. For quitting the bench calculator, you need to press Ctrl-D (^D), on an empty line. All the basic arithmetic operations: addition (+), subtraction (-), multiplication (*), quotient (/), remainder (%), power (^), brackets (()) are just there – with the C-like precedence & associativity rules. An example with all of them in use:

$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
2 + 2 * 3 - 5 + 21 / 4 * 6 # A basic maths statement
33
(2 ^ 2) ^ 3 # Another one with power & bracket
64
^D

Yes, you guessed it right. # starts a one-line comment as in shell, or like // in C++. For a multi-line comment, you may use /* */ as in C/C++. You may want that in case you are writing a complete program in bc. Yes, you can even do that. How? You may put your math statements (each one on a line by itself) in a file, say in prog.bc, as follows:

2 + 2 * 3 - 5 + 21 / 4 * 6 # A basic maths statement
(2 ^ 2) ^ 3 # Another one with power & bracket
quit # This will complete the program and not wait for more input

And then execute – yes I mean execute, you do not need to compile it – as follows:

$ bc prog.bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
33
64
$

Aha! You actually got the welcome message from bc and then your results. To avoid the welcome message, you may add -q option to bc, as follows:

$ bc -q prog.bc
33
64
$

You may also try out the difference in the output of the same program with a -l option, i.e. with real numbers. Then, / would be treated as a complete division, not just a quotient provider. Here’s what you would get:

$ bc -ql prog.bc 
34.50000000000000000000
64
$

Programming with bc

As soon as we say programming, the first thing flashing to your mind might be variables. Yes, so they are there. All the variables must start with a small letter alphabet and then may contain numbers or small letter alphabets. Yes, you read it right – only small letter alphabets (a,b,c,…,z). This is because, capital letters (A,B,C,…) are used to represent numbers in other bases greater than 10. Yes, bc have support for various bases from 2 to 16, and two variables associated with them: 1) ibase: defines the base for input; 2) obase: defines the base for output. By default, both are set to 10, as in our day-to-day usual maths. But can be modified, for more fancier base conversions. Here’s a snippet:

$ bc -ql
ibase # Show the current input base
10
obase # Show the current output base
10
obase=16 # Set the output base to 16
108 # Input in base 10; Output should be in base 16
6C
obase=10 # Set the output base back to 10
ibase=16 # Set the input base to 16
11 # Input now in base 16; Output should be in base 10
17
ibase=10 # Set the input base to 16. 10 is 16 in input base 16.
ibase=A # Set the input base to 10.
obase=2 # Set the output base to 2, i.e. binary
x = 2 * 5 - 1 # Set the variable x to 9 (input base 10)
x # Display the value of x (in output base 2)
1001
x * 2 # This should display 18 in base 2, but x is still 9
10010
obase=10
x++ # Post increment: Display the current value of x and then increment it
9
x # Display the incremented value
10
--x # Pre decrement: Decrement x and then display its value
9
^D

From the demo above, you might have already observed that there is nothing like declaring variable type or so – just assign them using = and then use them. Moreover, bc also have basic conditional and loop constructs: if, for, while, break, continue. And along with are the usual C-like relational (<, <=, >, >=, ==, !=), logical (!, ||, &&), and the operation-assignment (-=, +=, *=, /=, %=, ^=) operators. Note of caution: Their precedence and associativity rules may not be as in C. If you do not understand that, forget about it – just make sure to use brackets for whatever you want to operate first. Here goes two simple programs to demonstrate: 1) Computing the sum of the first n numbers (sum.bc); 2) Computing the product of the first n numbers, i.e. factorial of n (factorial.bc)

-------------------------------- file: sum.bc -----------------------------

print "Enter a positive number: "
num = read()
sum = 0
current_num = 1
while (current_num <= num)
{
	sum += current_num
	current_num += 1
}
print "Sum of first ", num, " numbers is: ", sum, "\n"
quit
-------------------------------- file: factorial.bc -----------------------------

print "Enter a positive number: "
num = read()
product = 1
for (current_num = 1; current_num <= num; current_num += 1)
{
	product *= current_num
}
print "Product of first ", num, " numbers is: ", product, "\n"
quit

The above programs can be tried out by issuing shell commands bc -ql sum.bc and bc -ql factorial.bc, respectively. But, what are those two words: print & read, doing there in the code. What else; they are just two built-in functions, displaying the message to the user and taking a number from the user, respectively. Functions? Yes, bc can do functions as well. That’s what would be our next camping. So, right now, just go ahead and try the above programs.

Third Article >>

   Send article as PDF   

Mathematics through the Shell

This article, which is the first part of the mathematical journey through open source, takes you through the basic mathematics through a shell.

Mathematics is something which is knowingly or unknowingly part of every moment of our life, starting from the interpretation of the moment – the time to shopping to advanced engineering calculations and computations. We have learnt mathematics from our childhood by counting. With the age of computers, we have been taught how to do mathematics with them. In this journey of mathematics, we are going to tour through the various open source softwares with their mathematical capabilities. Today, we start with the most preliminary one the shell.

Shell command ‘expr’

expr supports the basic arithmetic operations: Addition (+), Subtraction (-), Multiplication (\*), Quotient (/), Remainder (%) – with the C-like precedence & associativity rules. So, if that’s what you want, you may use it as follows:

$ expr 2 + 3
5
$ expr 34 – 67
-33
$ expr 23 \* 27
621
$ expr 43 / 6
7
$ expr 43 % 6
1
$ expr 2 + 2 \* 3 – 5 + 21 / 4 \* 6
33

Note the spaces between every one of the expr, numbers, and the operator – expr is very space-sensitive. The power of this simple command is its precision-less-ness. What I mean is, try out the following:

$ expr 1024 \* 1024 \* 1024 \* 1024 \* 1024 \* 1024 \* 1024 \* 1024 \* 1024 \* 1024

And you still don’t get an overflow, but 1267650600228229401496703205376, i.e. 2100.

Also, you may use variables. Here’s an example:

$ x=5; y=6; z=`expr $x + $y`
$ echo $z
11

However, it has its own limitation. Basic one being, you do not have the exponentiation operator. Moreover, you can’t change precedences by using brackets. And that’s where you start looking at the other options.

Shell’s arithmetic expansion

With this, we get the all the mathematical C operators, plus the exponentiation using **. We have the bracketing, and variable usage even without the cryptic $. It is achieved by putting the complete expression to be evaluated, between $((…)) – the arithmetic expander. Here’s a set of examples:

$ echo $(((2+3)*4-2**4/5%6))
17
$ x=y=8; echo $((3 << 4 | x | 2 << y))
568

There are some additional interesting ways to assign variables, as well, using let or declare -i.

$ let x=y=8 z='3 << 4 | x | 2 << y' w=z/3
$ echo $w
189
$ declare -i x=y=8 z='3 << 4 | x | 2 << y' w=z/3
$ echo $w
189

Note that the $((…)) has been replaced by single quoting in assigning the value to z. In fact, in most cases – see the assignment of w – it can be actually assigned directly as in C. Though the single quote for z is required to prevent the shell specially interpreting constructs like <<, >>, |, *, etc, and for it not to be space-sensitive. Otherwise, checkout, this example:

$ declare -i x=y=8 z=++x+y
$ echo $z
17

In fact, the variables can be declared as integer once, and then be operated any number of times, as follows:

$ declare -i x y z
$ x=y=8
$ z=++x+y
$ echo $z
17

And, finally here’s two simple ones:

$ echo $((2 ** 100))
0
$ echo $((2.6 + 3))
bash: 2.6 + 3: syntax error: invalid arithmetic operator (error token is ".6 + 3")

Oops!!! how come 2100 is zero, and we are not able to do real number operations. It has its own limitation. It is limited by the C’s long integer math, typically upto 64-bit computations on today’s computers; and by not having support for non-integer math. That’s where we would look out for something more powerful: the bench calculator.

Second Article >>

   Send article as PDF