Three surprises with bc

bc is a quirky but useful calculator. It is a standard Unix utility and is also available for Windows.

One nice feature of bc is that you can set the parameter scale to indicate the desired precision. For example, if you set scale=100, all calculations will be carried out to 100 decimal places.

The first surprise is that the default value of scale is 0. So unless you change the default option, 1/2 will return 0. This is not because it is doing integer division: 1.0/2.0 also returns 0. bc is computing 1/2 as 0.5 and displaying the default number of decimal places, i.e. none! Note also that bc doesn’t round results; it truncates.

bc has one option: -l. This option loads the math library and sets the default value of scale to 20. I always fire up bc -l rather than just bc.

The second surprise with bc is that its math library only has five elementary functions. However, you can do a lot with these five functions if you know a few identities.

The sine and cosine of x are computed by s(x) and c(x) respectively. Angles are measured in radians. There is no tangent function in bc. If you want the tangent of x, compute s(x)/c(x). (See here for an explanation of how to compute other trigonometric functions.) As minimal as bc is, it did make a minor concession to convenience: it could have been more minimal by insisting you use sin(π/2 – x) to compute a cosine.

The only inverse trigonometric function is a(x) for arctangent. This function can be bootsrapped to compute other inverse functions via these identities:

\begin{align*} \text{arcsin}(x) &= \arctan(x / \sqrt{1 - x^2}) \\ \text{arccos}(x) &= \arctan(\sqrt{1 - x^2 }/ x) \\ \text{arccot}(x) &= \pi/2 - \arctan(x) \\ \text{arcsec}(x) &= \arctan(\sqrt{x^2 - 1}) \\ \text{arccsc}(x) &= \arctan(1/\sqrt{x^2 - 1}) \end{align*}

The functions l(x) and e(x) compute (natural) logarithm and exponential respectively. bc has a power operator ^ but it can only be used for integer powers. So you could compute the fourth power of x with x^4 but you cannot compute the fourth root of x with x^0.25. To compute xy for a floating point value y, use e(l(x)*y). Also, you can use the identity logb(x) = log(x) / log(b) to find logarithms to other bases. For example, you could compute the log base 2 of x using l(x)/l(2).

Not only is bc surprising for the functions it does not contain, such as no tangent function, it is also surprising for what it does contain. The third surprise is that in addition to its five elementary functions, the bc math library has a function j(n,x) to compute the nth Bessel function of x where n is an integer. (You can pass in a floating point value of n but bc will lop off the fractional part.)

I don’t know the history of bc, but it seems someone must have needed Bessel functions and convinced the author to add them. Without j, the library consists entirely of elementary functions of one argument and the names of the functions spell out “scale.” The function j breaks this pattern.

If I could include one advanced function in a calculator, it would be the gamma function, not Bessel functions. (Actually, the logarithm of the gamma function is more useful than the gamma function itself, as I explain here.) Bessel functions are important in applications but I would expect more demand for the gamma function.

Update (September 4, 2019): Published a follow up post, More bc weirdness.

Related posts

9 thoughts on “Three surprises with bc

  1. bc is also great for proving that 6*9=42.

    set obase=13
    set ibase=10
    6 * 9
    42

    or for proving that 1 + 1 = 10
    set obase = 2
    set ibase = 10
    1 + 1
    10

  2. > bc is also great for proving that 6*9=42.

    Somebody knows their Douglas Adams. :-)

  3. Human Mathematics

    More surprises:

    -limits to ibase and obase

    -using single-letter variable names

    -sqrt, an exception to your variable rules and to the need for e(l(x)/2).

    -basic programming syntax

  4. I think you forgot the most important feature of running bc without -l option:
    It does arbitrary precision integer arithmetic!

    This proves that the 5th Fermat number is not a prime:
    $ echo ‘(2^2^5+1)%641’ | bc -q
    0
    $

    Also you can extend bc easily using “define” and add all the functions you want with your identities. “man bc” is worth reading.

  5. $ cat fs.bc
    define t(x) {
    return s(x)/c(x);
    }

    pi=4*a(1);
    $
    $ bc -lq fs.bc
    pi
    3.14159265358979323844
    t(0)
    0
    t(pi/4)
    .99999999999999999998

  6. I can’t thank you enough. I’ve been struggling with the implementation of asin, acos, acsc, asec, and acot in my bc-based rpn calculator script and your guidance has allowed me to finally sort this out. As a bonus, I’ve also been able to implement floating point exponents per your guidance, so yeah, today was a great day and I have you to thank for it. You can find the rpn calculator script on github, btw, if you’re interested in such a thing.

  7. bc is a kind of “decimal” calculator.
    Two branchs of bc program:
    – gnu bc : standalone program.
    – classical one: preprocessor of dc (early Unix, plan9, …): (dc does the arithmetics) (1975)

    Classical bc and dc are very well documented and the code (dc.c) is pretty easy to read.
    See : https://9p.io/sources/plan9/sys/src/cmd/dc.c
    Great papers published by bc and dc authors Robert Morris and Lorinda Cherry of Bell Labs :
    http://www.unixprogram.com/bc.pdf
    https://wolfram.schneider.org/bsd/7thEdManVol2/dc/dc.pdf

    One point drew my attention
    Numbers are stored as “strings” of digits in base 100 with a scale value. 101.01 is the number 1 01 01 with a scale of 2. Then addition, substraction, multiplication and division are made the same way we do on a sheet of paper with the concept of carry. The program never use “floating point arithmetic” of the processor. The processor only manipulates integers for 0 to 99.
    Truncation rules are applied. See : https://plan9.io/magic/man2html/1/dc

    NB : scale factor does not guarantee the accuracy of results. Writing math functions with bc must be done with extreme care to scales.

    Other tool: Hoc “high oder calculator” is a 64bits floatting point arithmetics simple language with a syntax close to bc.
    See: https://plan9.io/magic/man2html/1/hoc
    (available on plan9port for macosX, linux, unix and on 9pm for windows 10.)
    See : https://9fans.github.io/plan9port/

Comments are closed.