dozdc: A Tutorial
Dozdc is a powerful calculator program, but it does take a bit of getting used to. This tutorial will review postfix notation ("Reverse Polish notation," or RPN), which is used by dozdc, then examine dozdc's particular facilities.
Postfix notation is actually, in some ways, better than the way we're accustomed to writing our math (which is called "infix notation"). Most especially, it is unambiguous; there is no need for parentheses for grouping, because it's always perfectly clear what is to be done when.
Postfix notation utilizes a stack, to which and from which numbers are pushed and popped. Anytime a number is encountered, it is pushed onto the stack. When an operator is encountered, some of those numbers are popped off the stack, the operation is performed, and then the result is pushed back onto the stack. Eventually, all operations are completed, and the stack is empty.
Let's look at a contrived example to see how this works:
4 5 9 2 + * + 3 - =
We see first four numbers, and every time we encounter a number, we push them onto the stack. So our stack now looks like this:
And the rest of our equation looks like this:
+ * + 3 - =
(That is, that's the part of our equation that hasn't yet been pushed onto the stack.)
But now we hit an operator, +. An operator is never pushed or popped; rather, it pops certain things, does something to them, then pushes the result back onto the stack. An operator may be unary, meaning that it pops one number off the stack; binary, meaning that it pops two; or even ternary, meaning that it pops three.
We're all familiar with +; it's a binary operator which produces the sum of its two arguments. So we pop two arguments from the stack, add them together, then push the result back onto the stack. So we pop 2 and 9; we add them, to get E; and then we push E back onto the stack:
So our equation now looks like this:
* + 3 - =
Next is another operator, this time *. Remember the operators never get pushed to the stack; they pop things, do something with them, and then push the result. * is the multiplication operator; it pops two items from the stack, multiplies them, then pushes the result. The top two items in our stack are E and 5; so, in accordance with *, we pop the two of them, multiply them to get the result of 47; then we push that value back onto the stack. Our stack then looks like this:
And our equation is:
+ 3 - =
And we see another operator, +; by now we know what to do with it. Pop the last two values, add them, then push the result. So we pop 47 and 4, add then to get 4E, and then push that result back onto the stack. Our stack is now:
And our equation:
3 - =
If we get another binary or a ternary operator, we'll be in trouble, as there are not enough numbers in the stack to do what those operators want. (We'd need at least two; but we've only got one.) Fortunately, the next item in our equation is a number, not an operator; so we just push that onto the stack:
And our equation:
And no we do meet another operator: subtraction, the -. This is another binary operator, that pops two numbers, then subtracts them, then pushes the result onto the stack. Subtraction and division, however, are a bit different: they pop the top two items on the stack, but they reverse them before operating on them. This is due to the well-known principle that subtraction and division are not commutative; if we don't put them in the right order, we won't get the right answer.
So we pop 3 and 4E; we switch them around (giving us 4E and 3); we subtract them; (4E - 3 = 48); and then we push that value back onto the stack:
And our equation now only has word left: =. This is the equals sign; for dozdc, it means "pop a value off the stack and print it." There's only one number left on our stack, 48; so = will pop that and print it to your screen. And now our stack and our equation are both empty.
This all seems rather complicated; but here's what your session in dozdc will actually look like:
$> dozdc "4 5 9 2 + * + 3 - =" 48
It takes a little time to get used to thinking in postfix notation; but once you have, it becomes just as intuitive to you as the way you wrote problems in elementary school.
Now that we've got some familiarity with postfix notation in general, let's see what dozdc specifically has to offer.
Command-Line Options and Operators
The first and most important command-line option is the equation itself. This is the last option given to the command line, and consists of the equation you want dozdc to calculate, surrounded by quotation marks:
$> dozdc "0;2 sin 2 + =" 2;6000
Of course, dozdc, like all the dozenal programs, is a well-behaved Unix program, so you can also enter it and use it interactively by typing the command without an argument:
$> dozdc 0;2 sin 2 + = 2;6000 3;6 2 * = 7 quit
You can also feed it equations from standard input:
$> echo "0;2 sin 2 + =" | dozdc 2;6000
dozdc also has the -k and -e options, just as dec and doz have, the former for controlling precision of output and the latter for requesting output in exponential notation:
$> dozdc -k 2 "0;2 sin 2 + =" 2;60 $> dozdc -e -k 2 "0;2 sin 58 * =" 2;9Ee1
As the second example above shows, -e and -k can be combined as one wishes.
Many of dozdc's operators assume that their arguments are angles, which leaves the issue of what units the angles are expressed in. dozdc assumes that all angles are measured in unciaPi, the angular unit of TGM (each unciaPi is one-twelfth (uncia) of a straight angle). However, command-line arguments can tell dozdc to read them as either degrees or radians. -r signals radians, -d signals degrees:
$> dozdc "0;2 sin =" 0;5EEE $> dozdc -d "26 sin =" 0;5EEE $> dozdc -r "1 sin =" 0;X120
dozdc also provides operators to perform these same functions within an equation; so if you are in an interactive session and suddenly realize that you need, say, radians rather than degrees, you can change your setting within the session:
$> dozdc -d 26 sin = 0;5EEE rad 26 sin = -0;EX33
The operators are z, to return to unciaPi; d to use degrees; and rad to use radians.
The rest of dozdc's operators are pretty self-explanatory; the manual is the best reference for them.
One can due some (very) rudimentary programming with dozdc alone (anything complex would require using dozdc in another programming language). But for a few simple tasks, dozdc has capabilities which will suffice.
Because it is a well-behaved Unix program, dozdc will take input from standard input, even if redirected from a file. It also has the ability to assign values to named variables, so these variables are no longer variable once they've been assigned to. So consider a file you've created to find the cube roots of a variety of different numbers. In dozdc, roots are found by raising a base to a fractional power using the operator ^. E.g.:
$> dozdc "8 1 3 / ^ =" 2
Rather than calculate the exponent repeatedly (that is, doing 1 3 / each time you want to take a cube root), you can assign that value to a variable. Variables are any string of letters prefixed with a dollar sign; they simply pop the last value off the stack, and from then on that name is equivalent to that value in your session. So write the following in a file and name it dozdctest:
1 3 / $cuberoot 8 $cuberoot ^ = 23 $cuberoot ^ =
Then you redirect this file to dozdc on standard input:
$> dozdc < dozdctest 2 3
This is an extremely contrived example, not least because the whole $cuberoot construction could easily be replaced by 0;4. But it does give an idea of how to use dozdc's capabilities, should you need them.
By running dozdc with the option -v, you will get the visual or graphical version of the calculator. This works like most other visual computer calculators you've probably used: it's infix, not postfix; it takes its functions with arguments immediately following them in parentheses; and it works by clicking buttons with a mouse (or using the keyboard shortcuts).
The visual calculator is built using the xforms toolkit for the X windowing system, commonly installed on Unix-based systems (like GNU/Linux or BSD), and installable on Mac OS-X or whatever version is current. It will not work on Windows.
If you do not have the xforms libraries available, dozdc will not build. Either install the libraries to build it, or tell dozdc that you're not interested in the graphical version of the program. Go into the makefile and change -DXFORMS to -UXFORMS, and dozdc will happily build without the graphical calculator.
Screenshot of dozdc -v immediately upon starting the program.
Above, you see a screenshot of the window that pops up immediately upon running dozdc -v. It has a lot of buttons, some of which are not self-explanatory; so all buttons involve a mouseover text, or "tooltip," explaining their functions.
This calculator works in infix notation, not the postfix notation we described above. As such, you can enter your equations the same way you learned to write them and solve them at school:
Screenshot of dozdc -v with an infix equation in the problem field, ready to be solved.
dozdc -v then converts this equation to postfix notation, solves it, and replaces the problem field with the answer:
Screenshot of dozdc -v containing the answer to an infix equation.
The equivalent postfix equation is 8 2;3 - 3 * 4 + =, which, when run through dozdc, gives us the same answer.
Notice that the equation we solved here uses parentheses. Parentheses are part of how infix notation gets around the fact that it's inherently ambiguous; that is, that you're never exactly sure which operations should be done first. (The other part is order of operations.) Operations can be grouped by parentheses to any degree of nesting.
Functions take their arguments in parentheses following the function itself; functions which take multiple arguments separate them with commas. E.g., the arbitrary base log function, logb, take two arguments, the number and the base:
Screenshot of dozdc -v about to solve a multi-argument function.
This will give the logarithm of 3 to base 2, or 1;7029; it is equivalent to 3 2 logb =.
The functions on the far right side, with all contain the letter "M", are memory functions. "M+" adds the current contains of the memory to what's in the problem field; "M++" adds the current contents of the problem field to the memory; "M" replaces the problem field with whatever is in memory; and "CM" clears the memory entirely.
The number to the left of the problem field is the level of precision; that is, the number of digits to the right of the dit.
And that's all there is the graphical version of dozdc