## dc

This is an old post from an old blog; assets may be missing, links may be broken, and my opinions may differ considerably by this point…

### The Basics

First of all, if you're not familiar with postfix/RPN, it works on the principle of building a stack of objects and then operating on them rather than evaluating a statement of mixed up objects and operators. While many are used to the latter (infix or algebraic), it's often a rather inefficient method of computation. That's not really a debate for right now, however, because `dc` is a postfix calculator, so that's what you're stuck with. The thing to take away from all of this is that rather than calculations being input like `(5 + 3) * 2 =`, they are entered like `5 3 + 2 *`. In `dc`, whitespace is mostly meaningless. The only time it is really necessary is when putting multiple numbers on the stack. If we want to put 5, 3, and 2 on the stack, we must separate it out `5 3 2`, else we're putting a single number, 532 on the stack. This whitespace can be a space or a newline.

Hitting enter evaluates the current line. Basic arithmetic, the four commands `+`, `-`, `/`, and `*` work as expected. By default, nothing is returned to the screen; to get the last entry on the stack (the result of basic operations), the command `p` must also be executed. So, to get to the bottom of (32*2)/4, we would input `32 2 * 4 / p`, and get `16` returned. Of course, since whitespace is optional, this can also be entered as `32 2*4/p`. Note, for postfix newbies, that parenthesis are never necessary, as ambiguity is impossible.

The full contents of the stack can be displayed using the command `f`, and the stack can be fully cleared using the command `c`. The command `!` executes the remainder of the line as a shell command, thus I often clear my screen at the same time as my stack by executing `c!clear`. Two other stack manipulations that come up often are `d` to duplicate the last item on the stack, and `r` to swap (or reverse) the last two items.

Precision is arbitrary and fixed using the command `k`. Certain operations 'float' to an extent, that is, `2.25 2*p` returns `4.50`, though `4.50 2/p` does not follow, returning `2`. Thus, the first thing I usually do when I open `dc` is give myself a few points of precision, generally four, by entering `4k`. Upon doing this, `4.5 2/p` properly returns `2.2500`. The currently set precision can be pushed to the stack with the command `K`, a scheme that we'll see again with operating radices. If we've set `4k`, entering `Kp` should then return `4`.

Input and output radices (bases) are controlled with the commands `i` and `o`, respectively. To output in hexadecimal, enter `16o`. To input in binary, enter `2i`. If you're going to be working in a given radix (input and output), it's probably best for your sanity to adjust output first and then input, since such things take place immediately. That is, both `16o16i` and `16i10o` change both input and output to hexadecimal, but the first choice is much clearer. Likewise, when you need to switch again, be mindful of your current input radix. If we have `16i` set, and we need to get back to decimal, `10i` will not work (it will simply re-set input to hex). Instead, we need to remember we're inputting in hex, and use `Ai` instead. Conversion from-radix-to-radix are as simple as setting unmatched input and output radices. Assuming our input is set to decimal, and we need to convert to binary, we will just leave input alone and enter `2o`. Then, entering `48p` will convert that decimal 48 to binary, returning `110000`. We can then set `16i` if we want to convert from hex to binary, enter `AFp`, and get the result `10101111`. We can use `I` and `O` to push the respective radices onto the stack — but again, keep in mind, they will ultimately be output in the current output radix. Thus, `O` will always return `10`, making it useless outside of macros.

### Strings, Registers, Macros, Comparisons

For the most part, strings are handled pretty transparently inside of `dc`. Anything wrapped in square brackets is considered a string. Strings sit on the stack like numbers, and can be printed using the same `p` command. Strings can be used to prompt users for input, provide context for output, or, most importantly, define macros (akin to functions). A macro is simply a string containing a bunch of `dc` commands, such as `[8 4*]` being a macro that multiplies eight by four. Macros are, most basically, executed with the command `x`. Thus, `[8 4*]xp` will define our macro (pushing it onto the stack), execute it, and then print the result.

The manpage for `dc` claims that 'at least 255' registers can be defined. A register, for those unfamiliar, is akin to a variable. It's a place where information can be stored and then retrieved later. Registers in `dc` are complex — they contain their own stacks, and can also be indexed arrays. For the purposes of this primer, we're only going to deal with simple registers, each holding a single piece of data. This piece of data can be anything that would sit on the stack — that is, either a number or a string (including macros). The command `sr` is used to store a value in a register, and `lr` is used to load the value of a register back onto the stack. In both cases, `r` is a single character used to name the register. So, entering `42sa` puts the value 42 into a register named 'a.' Later, when we need to retrieve this undeniably useful number, we can execute `la`, and then `p` to see that we do, in fact, have our 42 back.

The ability to store and retrieve macros is one of the most powerful tools at our disposal in `dc`. If we need to multiply a number by 65535, we can create and store a macro `[65535*]sb`. Then, we can do things like (whitespace added for clarity from here on) `1 lb x p 2 lb x p 3 lb x p` and get back `65535`, `131070`, and `196605`, as expected. To make a macro that converts the current stack value into hex, we can enter `[O sz 16 o p lz o]sc`. To run this, we can leave our input as decimal, and do things like `15 lc x 64 lc x 255 lc x`, returning `F`, `40`, and `FF`.

Comparative operations in `dc` work by making the comparison, and if it ends up being true, running a set macro. Where r is the register containing the macro to run, the following comparators are available: `>r` (greater than), `<r` (less than), `!>r` (not greater than — put simply, less than or equal to), `!<r` (not less than — again, put simply, greater than or equal to), `=r` (equal to), `!=r` (not equal to). If we define a simple macro to echo 'true' upon execution, `[ [true] p ]sd`, we can do some quick comparisons. Entering `5 6 >d 6 5 >d 6 6 !=d 6 6 =d` will return `true`, (null), (null), and `true`, as our macro `d` is only executed on the two that are true — 6 greater than 5, and 6 equal to 6.

For loops can be constructed using comparators that call the macro they're inside. For instance, a typical `for (\$i=0; \$i<10; \$i++){ echo \$i; }` can be expressed as `0 si [li p 1+ d si 10>e] se lex`. First, we initialize `i` as 0 (\$i=0), then we set up our 'for loop' macro. Our macro first loads `i` back onto the stack, then it prints it out (echo \$i), adds one (\$i++), duplicates it (because storing it will pop one instance off the stack — and we need it to still be there for the next step), and finally checks if it's less than 10 (\$i<10), running the macro `e` if this is the case. We save this macro as `e`, and then run it, giving us a printout of the numbers 0-9.

### The end, for now

This should serve as a pretty good introduction to the operations of `dc`, while not covering all of its commands or capabilities. I'm bound to write more on the matter at some point, but until now have never seen a good way for newbies to break in to the program. The manpage covers things I didn't, including the more complicated register and array operations, as well as commands for getting extra division operation results, exponents (`6 3 ^ p` returns `216`), and square roots (`64 v p` returns `8`). All of the examples given in this primer can also be viewed in exploded, commented form in this document (if you're using vim, it'll look best with my dc syntax file). A distro's not a distro without `dc`, the deceptively simple little programmable RPN calculator.