Math from the Linux command line is one of those tasks that is not as straight forward as you may think. There are many tools that will allow you to perform mathematical functions accessible to you, but to perform simple arithmetic is not as simple as just entering some equation. You can use the echo command to perform basic mathematical problems but it does not allow for decimals making division in particular problematic. But if you want to simply add, subtract, multiply, or divide some values it is a handy resource:

echo $((512 * 1024))

That should return the value

524288

But,

echo $((4/3))

Returns the value of:

1

When it should be closer to:

1.333333

If you are going to use echo to perform simple arithmetic you need to follow the syntax:

echo $(( number symbol number))

Similarly the expr command can be used for simple arithmetic:

expr 4 + 7

Returns the result

11

But again, expr will not work well with decimals:

expr 4 \/ 3

Returns:

1

Note in this example the “/” had to be escaped.

To perform more complex mathematical operations from the command line use the bc tool. GNU bc is “an arbitrary precision calculator language” that will accept input from files, redirection or will run it’s own interactive session. Issuing bc by itself puts you into interactive mode:

screen shot 1

This is the same as executing bc with the -i, or –interactive, switch. At this point you can enter the statement:

4/3

Which will return

1

We seem to be in the same predicament as before, no decimals. This is because by default bc is operating with a scale of 0. Scale is a special variable in bc that determines the total number of decimal digits after the decimal point. To see the current value of scale while in bc execute:

scale

The default return should be

0

You can alter scale like so:

scale=3

Which sets scale to 3 decimal digits after the decimal point. So now:

4/3

Returns

1.333

To exit bc simply type quit.

There are a few other switches to the bc tool. The -q, –quiet, switch does not print the welcome message when entering into interactive mode. The -v, or –version, switch will show the version and copyright information for bc and then quit.

The -l, –mathlib, will load the standard math library when bc is executed. This sets the default scale to 20 and allows for additional math functions:

- sine – s(x), x in radians
- cosine – c(x), x in radians
- arctangent – a(x), arctangent returns in radians
- logarithm – l(x)
- exponential function – e(x)
- bessel – j(n,x)

Aside from evoking bc interactively, bc can operate on redirection:

echo 4/3 | bc

Returns

1

Again, we are missing the decimal point. There are to ways to resolve this:

echo 4/3 | bc -l

echo “scale=3; 4/3” | bc

Which return respecitvely

1.33333333333333333333

1.333

Recall that the -l switch loads the math library in and sets scale=20 by default, so there are 20 decimal digits after the decimal point. The second example we set the scale variable to 3 and thus returns 3 decimal digits after the decimal point.

There are three other special variables that alter the behaviour of bc:

- ibase = Set the base value of the input numbers, default 10 (decimal)
- obase = Set the base value of the output numbers, default 10 (decimal)
- last = Is set to the value of the last number printed

Both obase and ibase are set to decimal value by default. To switch to output in binary:

obase=2

To switch to input in Octal:

ibase=8

Note that changing this values will set the ibase and obase for all subsequent statements. To restore back to defaults either set each back to decimal:

obase=10

ibase=10

Or quit and restart bc. Issuing these as a redirection to bc will only set those values for that session:

echo “obase=2; 5*5; obase=10; last” | bc

Will return:

11001

25

The standard order of operations applies to the bc tool and can be altered with the use of parenthesis:

echo “5+2/2” |bc -l

echo “(5+2)/2” |bc -l

Return

6

3.50000000000000000000

The bc tool has it’s own language called bc. You can do far more than just calculator functions. You can define your own functions with the define command. For example:

define litsconverter (a) {

obase=2;

print “binary value is “;a*1; print “\n”;

obase=8;

print “octal value is “; a*1; print “\n”;

obase=16;

print “hex value is “; a*1; print “\n”;

obase=10;

print “all finished (p.s.: Ignore the 0 it returns at the end of every function if a return is not used”;

}

Now running:

litsconverter(15)

Will convert 15 (or whatever number you put in there) to binary, octal, and hex values the returns obase to decimal. The litsconverter function will remain available until you quit bc. Also note, that if we did not set obase back to decimal it would have stayed at hexidecimal until changed later on or you exited bc.

There is a lot more functionality to bc than just listed here. Consult the man page to get started on how to create your own functions to unlock the power of bc.

- man bc
- Linux Journal: Work the Shell – Solve: A Command-Line Calculator
- Exponential Function – Wikipedia
- Bessel Function – Wikipedia

If the video is not clear enough view it off the YouTube website and select size 2 or full screen. Or download the video in Ogg Theora format:

- Episode 025 – date Ogg Theora Video – Archive.org

Thank you very much!

- Ogg file hosted by Hacker Public Radio
- Speex file hosted by Hacker Public Radio
- Mp3 file hosted by Hacker Public Radio

Great show on bc. I use it almost daily as my desktop computer calculator. Even with a multimedia keyboard with a calculator button, I find that typing “bc” in a terminal window is easier and faster for me.

I wanted to call out one of my uses for bc. Since normally my math is needed in the body of an email, and I use mutt+vim for my email. I tend to do my math directly inside vim by calling a read in from stdin command line output. The method I use is often for converting decimal hours into minutes. I invoke this from the Normal mode of vim using ‘:r ! echo “.27*60” |bc’ which will read in the result as a new line where the cursor is in the file. This is needed since its impossible to use bc in interactive mode directly from inside vim. And while it does serve very similar to expr or the echo statements which evaluate (as listed in the beginning of the blog post) you gain all the regular caluclator functions that would normally enjoy in interactive mode.

I would like to point out that I didn’t strictly hear on the podcast was that if you set the scale value in the interactive mode of bc and do not launch it with a flag that alters the scale setting it remains persistent. Since in my system I always set “scale=2” my results are always returned with the hundredths decimal point and in my example I would get a return of 16.20 which would be 16.2 minutes.

Great show, keep up the good work.

—

CafeNinja