# #21: The command line calculator bc

Performing calculations on the command line is very handy and `bc`

is the tool which does it for you. Also bash can do some calculation stuff, but that's not very intuitive. For instance

`echo $[4*4]`

calculates `4*4`

. That stills looks easy, but as soon as you want to perform more complex calculations, this becomes a hassle. Bash is built for different things than calculation and so `bc`

is the better choice. It can do much more for you and its syntax is ways easier.

There are three ways to use `bc`

. The first is to use files. Write your `bc`

script into a file an then call

`bc file`

Use `-q`

to suppress the header of `bc`

. The second way is to use STDIN:

`echo '1+2*3/4' | bc`

and last but not least the third way is the interactive mode. Just run `bc`

and you get a shell-like prompt where you can insert your operations. Quit `bc`

by typing `quit`

and hitting enter.

It's up to your needs, which way you choose, there is no difference in functionality.

As you've already seen: basic arithmetic operations can be done with the operators `+`

, `-`

, `*`

and `/`

. But there's much more. You can, e.g., calculate the square root:

`sqrt(x)`

where `x`

is any number. The syntax of `bc`

is very C-like. Therefore you can also assign values to variables:

```
var=123
print var
```

You can also print strings to the screen:

`print "Hello World\n"`

There are also some special variables. For instance `scale`

:

`scale=10`

That sets the decimals form default 0 to 10. Examine the difference with

```
10/3
scale=10
10/3
```

The first line only generates `3`

, the third one `3.3333333333`

. Two other important special variables are `ibase`

and `obase`

, which define the number system; the default is 10 (decimal system). `ibase`

specifies the input number system and `obase`

the output number system. With these variables you can, e.g., convert hex digits to binary:

```
ibase=16
obase=2
F
```

Output is: `1111`

(binary for hex `F`

).

`bc`

also let's you define functions like in any normal programming language. The language construct for this is `define`

:

`define by2(x) { return x*2 }`

You can now call this function:

`by2(6)`

The output is `12`

.

Also conditions and loops are possible:

```
while (var < 5) {
++var
}
print var
```

```
if (by2(4) < 10) {
print "Foobar\n"
}
```

`bc`

also has some pre-defined functions for basic math operations. These are `s(x)`

for the sine, `c(x)`

for the cosine, `a(x)`

for the arctangent, `l(x)`

for the natural logarithm, `e(x)`

for raising the Euler constant to the power of `x`

and `j(n, x)`

for the Bessel function. These functions are all available when executing `bc`

with the `-l`

parameter, which loads the particular math library.

This is all very useful, but one thing has always bothered me is the precision of irrational numbers. `bc`

obviously does a pretty bad job on approximating these numbers. If I execute the following

`l(e(3))`

I always get 2.99999999999999999999 instead of 3. That's the same if I, e.g., want to calculate the cube root of, let's say, 8:

`e(l(8)/3)`

There I get 1.99999999999999999998 instead of 2. I know, this behavior should be platform specific, but it should be possible to get nicer results here by automatically rounding periods. As yet I haven't found a way to make `bc`

handle this smarter. If you know one, please leave me a comment.

Learn more about `bc`

:

## Trackbacks

## Comments

You’ve linked my FAQ, which (now) mentions the trunc() function I’ve written which attempts to remedy the largely aesthetic repeating nines problem (as well as repeating zeroes).

Bear in mind that your examples differ from the correct value by a very small amount. In fact e(3) on its own, sqrt(2) and even 2/3 necessarily differ from the correct value by a very small amount – bc stores all results as a decimal fraction – yet most people take those errors for granted, deliberately ignore them or are even unaware there’s a difference.

To demonstrate this behaviour in the worst case, try

scale=20;(2/3)*3

at the bc console. The error here is tiny; one part in fifty quintillion, but it’s unsightly when we’re used to seeing nice round numbers and instead we see nines.

As to the trunc(x) function I mentioned, here it is:

define trunc(x) { auto os,s; os=scale-5 if(scale>=A){ scale-=4 s=1;if(x<0)s=-1 x+=s*A^-scale scale-=1;x/=1 } for(scale=0;scale<=os;scale++)if(x==x/1){x/=1;break} scale=os+5;return(x) }

*The comments field turns the less thans and greater thans into < and > respectively, which I can’t seem to work around.*

Then try:

scale=20;f=(2/3)*3;f;trunc(f)

which will set f to a sub-optimal but close value to 2, display that value, and display the value after trunc() has successfully attempted to ‘fix’ it.

Hi, thank you very much!

Such a truncation function is of course a workaround but I think in this case a decent solution.

I know the problem with the HTML entities; it just occurs within code fields and seems to be a plugin conflict. I’ll try to fix that.

RT @reflinux: #Advent series “24 Short #Linux #Hints”, day 21: The #command line #calculator #bc http://bit.ly/fwRlDO