# Calculating on the Command Line

**Note:** there's a public repository containing the source code and any formal
documentation for the program that this post is about.

There are any number of ways to get your computer to do math, but I wanted a command line program to quickly, easily and in as natural a way as possible do basic calculations like summing a few numbers, calculating an item's after-tax price or doing basic unit conversions. I also wanted it to operate on both integer and real values and give results to a reasonable number of decimal places.

Of course, I wasn't going to implement the part that did the actual math
since existing programs already do that. One of the earliest versions of my
`calc`

script was just a minimal wrapper around one such program: `bc`

. Aside
from code to output a usage message my script's implementation was basically

echo "scale=2; $*" | bc

which combined all of the command line arguments into a single expression for
`bc`

to evaluate, after setting the default number of digits after the
decimal to 2 (which is sufficient for most calculations and ideal for ones
involving (my local) currency). Note that the result from `bc`

may be an
integer or may have fewer or more than the default number of digits after the
decimal depending on what's appropriate for the particular computation.

(Also note that the default number of digits after the decimal affects intermediate as well as final results of calculations, and so the result of a calculation with fewer digits after the decimal may not just be a rounded - or even truncated - version of the result of the same calculation done with more digits after the decimal.)

This version worked pretty well, especially with `=`

(that is, a single
equals sign) as a symbolic link to `calc`

:

= 2 + 2 = 12.34 + 56.78 + 90.12 = 5 / 3 = '42.5 * 17' = 42.5 \* 17

4 |

159.24 |

1.66 |

722.5 |

722.5 |

Having to quote or escape multiplication signs to protect them from being expanded by the shell into every file in the current directory was less than ideal, but a simple - if a little brute-force - change

echo "scale=2; $*" | tr 'x' '*' | bc

fixed that. Now the 'x' character could be used as a multiplication sign as well:

= 42.5 x 17

722.5

So now the four basic mathematical operations could be used without having to quote or escape anything. Parentheses still required - and still do require - escaping or (usually easier) quoting, however:

= '(23.40 + 12.34) x 1.12'

40.02

The final tweak - until very recently - was to allow the default number of digits after the decimal to be customized on a per-session or a per-command basis. The implementation effectively became

echo "scale=${CALC_SCALE:-2}; $*" | tr 'x' '*' | bc

which allowed the `CALC_SCALE`

environment variable to be used to specify
that default:

= 5 / 3 export CALC_SCALE=4 = 5 / 3 CALC_SCALE=8 = 5 / 3 = 5 / 3 CALC_SCALE= = 5 / 3

1.66 |

1.6666 |

1.66666666 |

1.6666 |

1.66 |

And that's where it stood until I looked at it again in preparation for
writing this post. While it's still not a very long script its core is
definitely no longer a one-liner. But calculations can now include the
mathematical constants `pi`

and `e`

, as well as the `sin()`

, `cos()`

,
`atan()`

, `ln()`

and `exp()`

functions, and the default number of digits
after decimal is now easier to customize:

- the
`CALC_SCALE`

environment variable's name was too long for convenient use on the command line, so the`sc`

environment variable can also be used:`sc`

is intended for use with a single invocation of`calc`

, while`CALC_SCALE`

should be used over larger scopes - if the program's basename is an equals sign (=) preceded by one, two or three digits then the number that those digits represent will be the default number of digits after the decimal

(A program can be given an additional basename by creating a symbolic link to
it: for example, executing `ln -s calc 15=`

will create a symbolic link that
can be used to perform calculations with a default of 15 digits after the
decimal place.)

So calculations like the following are now possible:

= 2 x pi x pi export CALC_SCALE=5 = 2 x pi x pi sc=8 = 2 x pi x pi = 2 x pi x pi 8= 2 x pi x pi 9= 'sin(1.2) x sin(1.2) + cos(1.2) x cos(1.2)' sc=10 = pi

19.71 |

19.73917 |

19.73920875 |

19.73917 |

19.73920875 |

0.999999996 |

3.1415926535 |

Will I use this additional functionality often enough to warrant the added
complexity? I'm not sure. But if I didn't add it then there wouldn't be any
way for me to find out. It's not a huge increase in absolute complexity in
this case (even if it is in relative complexity), but I think the same
reasoning applies to other, larger programs as well. Of course, I could
always remove the new code if it turns out I don't use it, but who ever does
*that*?

As a final note, Emacs users can use the `quick-calc`

command to access
similar functionality, as I recently found out. Well, rediscovered actually,
since it turns out that I've had a keybinding for it in my Emacs
configuration since 2018 and had completely forgotten about it: a not
uncommon occurrence.

## Selected Commit History

Some selected dates in the `calc`

script's original commit history (which is
different from its GitHub commit history):

- initial commit
- can use 'x' in place of '*'
- can use environment variable to set digits after decimal
`sc`

environment variable
can use shorter - can use pi, e, sin(), cos(), atan(), ln() and exp() in calculations

If you'd like to support this site then check out my web app InEveryNook.com and see if it's of interest to you, pass it along to anyone you think might be interested in it, or both. Thanks!