Exploring a Linux or other *Nix equivalent, you come across an ancient, mysterious artifact: dc. There it is in /usr/bin, but what is it for? It is for die-hard command-line wizards, that’s what it’s for. But learn its syntax, and if you’re the kind of hacker who hates clicking buttons on a virtual desktop calculator, you might start doing all your calculating with dc and be hooked!
dc is the command-line Unix “Reverse-Polish Notation”(RPN) calculator. The name stands for “desktop calculator”. OK, so what is a Polish calculator and why would you want to reverse one? The math that you do in school uses infix notation, with the operator between the numbers (3 + 5). Prefix notation puts the operator first (+ 3 5) and is what the Lisp language uses. The prefix notation is known as “Polish notation” after the nationality of Jan Łukasiewicz who invented it. Postfix notation, then, has the operator at the rear (3 5 +), and so is also the reverse of Polish notation.
What’s the difference? In computer programming, you have to specify what order you want a multi-part calculation to be in. Everybody is familiar with the old order of operations problem of A*B-C. For A=5, B=3, C=2, multiplying first and subtracting second gives you 13, while subtracting first and multiplying second gives you 5. To specify which operations you want performed first, you have to either memorize the complex orders of operations (which may change from one programming language to the next) or use a lot of parenthesis ((A*B)-C) or (A*(B-C)). Hey, that’s what everybody complains about in all those languages that use parenthesis!
In dc, we eliminate the problem this way:
…gives 13, and
…gives 5. What’s going on here is that it uses a “push-n-pop” stack , a data-storage system familiar to programmers of Assembly and Lisp. When you enter a number, it gets pushed onto the stack. When you enter an operator or a command, it pops the latest affected numbers off the stack, performs the operation, and pushes the answer back onto the stack. The commands (which are all single-letter) have various other effects.
Reading through the dc man page will give you the commands of dc, but will do little to help you grasp the unfamiliar concepts if you aren’t used to using an RPN calculator. So consider this post to be the supplemental reading to the dc man page.
Let’s look at one of the reasons to use dc as opposed to the Bash echo command or Python: you can set the floating-point precision easily. The command to do that is “k” (first thing you thought of, right? It stands for “krecision”!) and it takes the most-recently-pushed number as an argument. So you can say “2 k” to set the precision to two decimal places for dollars-and-cents operations. While we’re at it, let’s introduce the “v” command, which computes a square root. This makes sense if you’ve seen it in ASCII art:
So, the dc way to get the square root of two to ten decimal places is:
which gives back 1.4142135623 and returns you to a prompt, lickety-split. We could also make it less confusing by using spaces:
That’s “10… set this as the precision… 2… calculate this number’s square root… print the result”. The only time you need to use spaces is to separate two numbers (so 10 and 30 don’t become ‘one-thousand-and-thirty’). For that matter, you can also run dc interactively. The “-e” thingie says to evaluate the expression (and exit immediately). But check out this session:
…the “q” is the command to quit. Since you can also omit spaces in interactive mode, we could also go:
Story problem: Johnny is taking a contract for a famous politician to write 20 Facebook posts @ 600 words each, for which he intends to charge 2¢ per word. How much money will the client pay?
And we’re going to add one more command: “f” dumps the whole dang tootin’ main stack to the screen, instead of just printing the first value.
dc also has a memory feature. You can call the memory ‘R’ (register?) and this is of course another stack. So you can store a value for later use. Pop a value off of the main stack and push it onto the R stack with “sR” and pop the value back off the ‘R’ stack and push it back onto the main stack with “LR”. To copy the value off the register stack (as opposed to moving it) you say “lR”. By the way, registers can have ANY single-letter name you want! But they have to be initialized first before they are used (with a command like “sR”). Puzzled frowns? Here, my pupils:
Let’s experiment with the previous calculation, using this new knowledge:
What we did: the previous tweet-count problem, pushed it to Register, copied it back, printed the stack to show where we are, multiplied the Register times 15% and pushed it onto the stack and showed the stack again, then subtracted the second value from the first value and showed the stack again.
Story problem #2: Johnny is taking a contract to write 20 Facebook posts @ 600 words each, for which he intends to charge 2¢ per word. Johnny’s agent charges 15% commission for finding him these weird off-brand jobs. What is Johnny’s take-home before taxes?
Feel free to indulge in some primal scream therapy, not only at Johnny’s ridiculously low income, but at the fantastically terse command he used to figure it. The other beauty of dc is that it is a relatively powerful calculator (supporting +*-/ (standard four functions) % (modulus) ~ (division and remainder) ^ (exponent) | (modular exponent) and v (square root)) which can be included in a script or command line. It can also do base-conversions on-the-fly with the “i” (input radix) and “o” (output radix) commands. So, 256 in hexadecimal is: