Thursday, August 13, 2009

Shell as calculator

The standard Linux shell (bash) can serve us as calculator. The bash itself is only limited to integer numbers, however there is also bc command. Bc stands for binary calculator and allows to do numbers of calculations using floating point math as well as conversions. First let's look at standard shell possibilites:

$ echo $((2+2)
4

$ echo $((2+2*(3*4)))
26

modulo operator

$ echo $(10 % 3)
3

power operator

$ echo $((2**3))
8

bitwise operators (bitshifting):

$ echo $((2<<3))
16

$ echo $((10>>1))
5

There is one trick as to bitshifts. Shifting the number by 1 bit left means multiplying by 2, shifting it by 1 bit right means dividing by 2. Bitshifting is faster than multiplying but it has the meaning in assembly language programs, not the linux shell :).
Of course we can assign the result to variabe to use it later:

$ VALUE=$((100/4))
$ echo $VALUE
25

Bash is good only for integer calculations. Bc is much more powerfull tool. To calculate anything with bc we usually pipe the output of echo
to bc:

$ echo 2+2 | bc
4

echo 2.56*2.66 | bc
6.80

We can set the precision with scale parameter:

$ echo "scale=4; 2.56*2.66" |bc
6.8096

To calculate the power we use ^ (in bash it means bitwise negation):

$ echo 2^10 | bc
1024

Bc as base converter :)

Apart from simple calculation bc can be used as base converter. To convert among decimal, hex and binary numbers we use ibase (input base) and obase (output base) parameters. The default base is 10. Let's see some examples:

$ echo "obase=16; 255" | bc
FF

$ echo "obase=2; 255" | bc
11111111

However to convert from binary to decimal we have to set obase as hex number (10 is A). The reason for that is 10 in binary is 2, so the obase would be 2, becase ibase is set to 2 and interprets decimal 10 decimal as binary 2:

$ echo "ibase=2; obase=A; 1000" | bc
8

When the switch -l is used the bc is preloaded with math library and default scale is set to 20. This allows to do some more advanced calculations such trigonomery math. The argument is given as radians. To calculate sine of 30 radians type:

$ echo "s(30) | bc -l"

We can calculate PI very easy up to many digits after period (set with scale):

$ PI=$(echo "scale=10; 4*a(1)" | bc -l)
$ echo $PI
3.1415926532

Now we can convert radians to degrees with the formula:

degrees=radians*PI/180

Shell calculator

It's worth to write short script which can be used as calculator.

#!/bin/bash
echo "scale=4; $1" | bc

Save it as calc and give execution rights:

$ chmod u+x calc

From the root shell copy it somewhere i.e. to /usr/bin to make it visible system-wide.

$ su -c "cp calc /usr/bin/"

Use it this way:

$ calc 6.5*6.5
42.25


2 comments:

  1. scale doesn not seem to work
    tonu@x3200:~/tyros/tonu$ echo "scale=1; 1.2222222*1.11111111111111111" |bc
    1.35802466666666666
    tonu@x3200:~/tyros/tonu$ echo "scale=2; 1.2222222*1.11111111111111111" |bc
    1.35802466666666666
    tonu@x3200:~/tyros/tonu$ echo "scale=20; 1.2222222*1.11111111111111111" |bc
    1.35802466666666666530
    tonu@x3200:~/tyros/tonu$

    ReplyDelete
    Replies
    1. I know this is super late but scale only works for precision in division. Precision in multiplication is well defined.

      Delete