# Some bc stuff

When I sit down at my computer to do a longish series of calculations, I open a Jupyter console session. That gives me an interactive Python environment with all of NumPy and SciPy at my disposal. But when I just want to do a quick little calculation or two, the time it takes to start up Jupyter gets in the way. That’s when bc comes in handy.

I don’t know why bc is named bc. The c part is obviously “calculator,” but I’m not sure what the b is for—”basic,” maybe? It was originally a front end for the older dc (“desk calculator”), but the GNU version, which is what we have on our Macs, is a standalone program.

Update Feb 23, 2021 2:05 PM
According to this page, the b stands for “Bell,” which seems plausible.

Update Feb 22, 2021 2:24 PM
Kevin Likes remembers that where he went to school the b was thought to be “bignum.” Also plausible, since one of the bc’s main features is its ability to do math at arbitrarily large precision.

If anyone knows Lorinda Cherry, can you ask her?

I used to think bc was useless—I don’t trust a calculator that tells me 1/2 = 0—but I changed my mind after seeing what John Cook has done with it (here’s a good example). Although its defaults are weird, bc is quite nice if you start it up the right way, which is

bc -lq


where the -l option tells it to load in it small library of functions and sets the scale parameter (which controls the number of digits after the decimal point) to 20, and the -q option tells to start up without printing out the copyright information. Rather than remembering to type this every time, I have an alias in my .bashrc file:

alias bc='bc -lq'


I said bc has a small library of functions, and I wasn’t kidding. Here they are:

bc function math function
s(x) sine
c(x) cosine
a(x) arctangent
l(x) natural log
e(x) exponential
j(n, x) nth Bessel function

The more time you spend with Unix, the more you realize how much the folks from Bell Labs hated typing.

I like terse commands, too, but I think bc goes too far. Also, I prefer having a tangent function to constantly dividing sine by cosine. So I have a dotfile in my home directory, .bc, that defines the common names for the standard functions and adds a few more to make my life easier. Here it is:

 1:  # Trig
2:  pi = 4*a(1)
3:  define deg(x) { return 180*x/pi }
4:  define rad(x) { return pi*x/180 }
5:
6:  define t(x) { return s(x)/c(x) }
7:  define sin(x) { return s(x) }
8:  define sind(x) { return s(rad(x)) }
9:  define cos(x) { return c(x) }
10:  define cosd(x) { return c(rad(x)) }
11:  define tan(x) { return t(x) }
12:  define tand(x) { return t(rad(x)) }
13:  define atan(x) { return a(x) }
14:  define atand(x) { return deg(a(x)) }
15:
16:  define asin(x) {
17:   if (x == 1) {
18:     ans = pi/2
19:   } else {
20:      if (x == -1) {
21:       ans = -pi/2
22:      } else {
23:        ans = a(x/sqrt(1 - x^2))
24:      }
25:    }
26:    return ans
27:  }
28:  define asind(x) { return deg(asin(x)) }
29:
30:  define acos(x) {
31:    if (x == 0 ) {
32:      ans = pi/2
33:    } else {
34:      if (x > 0) {
35:        ans = a(sqrt(1 - x^2)/x)
36:      } else {
37:        ans = a(sqrt(1 - x^2)/x) + pi
38:      }
39:    }
40:    return ans
41:  }
42:  define acosd(x) { return deg(acos(x)) }
43:
44:  # Exponential
45:  define exp(x) { return e(x) }
46:  define log(x) { return l(x) }
47:  define ln(x) { return l(x) }
48:  define log10(x) { return l(x)/l(10) }
49:  define log2(x) { return l(x)/l(2) }


Most of this is pretty obvious, but a few comments are in order:

• The arcsine and arccosine functions are defined to avoid division by zero errors when their arguments are 1, -1 (for asin), or 0 (for acos).
• In keeping with the usual definitions, asin returns an angle between π/2 and -π/2, and acos returns an angle between 0 and π.
• Old Fortran programmers (are there any other kind) will recognize the “degree” versions of the trig functions. Measured angles are always given in degrees, and it’s more convenient to have functions that work with those kinds of arguments.
• Old habits die hard, and although I know that log is the natural logarithm in every programming language, I still sometimes type ln. So I added a function that allows me to keep making that mistake without punishment.

To get these definitions loaded into bc, I have this line in my bashrc:

export BC_ENV_ARGS=\$HOME/.bc


BC_ENV_ARGS is a poorly named environment variable that tells bc to run the given file on startup. With this definition and the alias mentioned above, whenever I type bc at the command line, I get all of these functions and 20 decimal places of precision.

If I ever feel the need for more functions, this page has quite a few.

One last thing. When you don’t give it a file name argument, bc goes into interactive mode. This is nice when you have a few calculations to do, but it does force you to quit bc when you’re done (which you can do with either the quit command or by typing ⌃D). If you have just one calculation to do, it’s faster to give bc the command through a here string, like this:

bc <<< "5*cos(35) - 5*sin(35)"


Of course, like the Bell Labs people, I’m far too lazy to type out all those less than signs, and I can never remember to type the opening quotation mark before the calculation. So I made a TextExpander snippet that types out the boilerplate and puts the cursor between the quotation marks. All I have to type is the calculation itself.