Est. 1971 Intermediate

Unix DC

The reverse-Polish, arbitrary-precision desk calculator that was the first program ever run on Unix's PDP-11 — and still ships with virtually every Unix-like system today.

Created by Robert Morris and Lorinda Cherry

Paradigm Stack-based, Reverse Polish
Typing Untyped (arbitrary-precision numbers and strings)
First Appeared 1971
Latest Version GNU dc 1.5.2 (May 2025)

Unix dc (for “desk calculator”) is a reverse-Polish, arbitrary-precision calculator language and one of the oldest pieces of software still in everyday use. Written at Bell Labs by Robert Morris and Lorinda Cherry, dc predates the C programming language, predates Unix on the PDP-11 — it was, by Ken Thompson’s account, the first program run on that machine — and appears in the very first edition of the Unix Programmer’s Manual, dated November 3, 1971. More than fifty years later, an implementation of dc ships with virtually every Unix-like operating system, its terse single-character commands and unbounded precision essentially unchanged.

dc is often described as the oldest surviving Unix language: beneath its calculator exterior is a genuine programming language, with registers, strings, executable macros, and conditionals that together make it Turing-complete.

History & Origins

Before Unix Had an Assembler

dc’s origin story is inseparable from the origin of Unix itself. When Bell Labs acquired a PDP-11 around 1970 — the machine on which Ken Thompson and Dennis Ritchie would build the Unix that conquered the world — the system arrived before its own software ecosystem existed. dc, written in B, the typeless predecessor of C, was the first program to run on the new computer, before even an assembler was working. Thompson has opined that dc was the very first program written on the machine at all. A humble desk calculator was, in effect, the shakedown cruise for the hardware that Unix and C grew up on.

The First Edition Manual

The First Edition Unix Programmer’s Manual (November 3, 1971) documents dc (I) as “an arbitrary precision integer arithmetic package.” The 1971 dc was already recognizably the language used today: numbers pushed on a stack, + - * / % operating on the top two entries, s and l to store and load named registers, d to duplicate the top of stack, and p to print it. Input beginning with a zero was taken as octal. The manual’s worked example computes the monthly, weekly, and hourly rates for a $10,000-a-year salary — in pennies, since this version handled only integers — and its BUGS section admits with early-Unix candor that the remainder operator “doesn’t work correctly.”

The attribution of dc is a small piece of Unix lore in itself: the program is credited to Robert Morris and Lorinda Cherry, whose names appear on the definitive dc paper, while the First Edition manual page lists “ken” — Ken Thompson — as its owner, a reminder of how small and intertwined the early Unix group was. Morris went on to become chief scientist at the NSA’s National Computer Security Center; Cherry became one of the most influential members of the Unix group, later co-creating bc and the Writer’s Workbench text-analysis tools.

Maturity by Seventh Edition

By Seventh Edition Unix (1979), whose manual includes Morris and Cherry’s paper DC – An Interactive Desk Calculator, the language had grown into its final shape: arbitrary-precision decimal fractions with a user-controlled scale, strings enclosed in square brackets, the x command to execute a string as a macro, comparison commands that conditionally execute registers, and array storage. Those additions turned a calculator into a programming language — recursion via macros that invoke themselves gives dc full Turing-completeness.

Design Philosophy

Reverse Polish, No Ceremony

dc is a pure stack machine exposed directly to the user. There is no operator precedence to remember because there are no infix expressions: operands go on the stack, operators pop them and push results. Nearly every command is a single character. This makes dc programs famously terse — and famously cryptic — but the design is entirely consistent: learn perhaps two dozen characters and you have learned the whole language. It is worth noting that dc’s reverse-Polish interface predates the HP-35, the handheld calculator that popularized RPN, which was introduced in 1972.

Arbitrary Precision as a Foundation

From the beginning, dc’s defining capability was arithmetic on numbers of unlimited size. In 1971, when machine words were 16 bits, dc would happily multiply hundred-digit integers. That capability is why dc kept finding new work for decades: it was the readily available bignum engine on every Unix system, whether the caller was the bc compiler in 1975 or a three-line RSA implementation in 1995.

A Calculator That Is Secretly a Language

dc’s programmability is built from a few orthogonal pieces rather than dedicated syntax: strings are values, registers hold values, and x executes a string. A conditional is just “compare and maybe execute this register”; a loop is a macro that re-executes itself. There are no keywords anywhere in the language.

Key Features

  • Arbitrary-precision arithmetic — integers and, since the 1970s, decimal fractions of unlimited size, with the scale (digits after the decimal point) under program control via k
  • Pure stack model — all computation happens on a single value stack manipulated by one-character commands (d duplicate, r swap in modern implementations, f dump the stack)
  • Named registers — 256 single-character registers, each of which is itself a stack in modern implementations
  • Strings and macros[...] pushes a string; x executes one as dc code, and macros calling themselves provide recursion and loops
  • Conditional execution — comparison commands (<x, >x, =x and negated forms) pop two values and execute a register on a match, providing branching
  • Arrays — indexed storage and retrieval per register via : and ;
  • Input/output radix controli and o set input and output bases independently, making dc a handy base converter
  • Turing-completeness — the macro-and-conditional combination is sufficient for general computation, unusual for something billed as a calculator

Code Examples

The classic first taste — push two numbers, add, print:

1
2
$ dc -e '2 3 + p'
5

Set the scale to 20 digits and take a square root:

1
2
$ dc -e '20k 2 v p'
1.41421356237309504880

Factorial via a recursive macro — the idiomatic demonstration of dc as a real language. The macro is stored in register F and calls itself while the top of stack exceeds 1:

1
2
$ dc -e '10 [d1-d1<F*]dsFxp'
3628800

Reading it character by character: [d1-d1<F*] pushes a macro that duplicates the current value, subtracts 1, and — if the result is still greater than 1 — recurses before multiplying; dsFx duplicates the macro string, stores one copy in register F, and executes the other; p prints the result, 10!.

Relationship with bc

No account of dc is complete without bc, its lifelong companion. In 1975, Lorinda Cherry wrote bc for Version 6 Unix as a front end to dc: bc parsed familiar infix expressions, variables, and C-like function definitions, compiled them into dc’s postfix commands, and piped the result to dc, which performed every actual calculation. For decades, users who thought they were using bc were running dc underneath.

The relationship later inverted. POSIX standardized bc in 1991 but never standardized dc, and the GNU implementations decoupled the pair: Philip Nelson’s GNU bc (first released in 1991) is a self-contained bytecode interpreter, while Ken Pizzini’s GNU dc — distributed in the same package — is built on bc’s arithmetic library. The child now carries the parent.

Evolution

dc’s implementation history spans the whole arc of Unix. The original B-language program was succeeded by the C implementation documented in the Seventh Edition manual, which flowed into the BSDs and commercial Unixes; Plan 9 carried its own dc forward from the research lineage. In the free-software era, GNU dc became the version most Linux users encounter, and it remains actively maintained — GNU bc 1.08 with dc 1.5.0, released in early January 2025 (with point releases through May 2025), added readline and libedit line-editing support and a sandboxing option that disables dc’s ! shell-escape command.

The most significant modern development is Gavin D. Howard’s independent bc/dc implementation, written in ISO C99 and permissively licensed. FreeBSD 13.0 (released in 2021) replaced its bc and dc utilities with Howard’s versions — its release notes cite GNU bc extensions, fixes for POSIX-compliance issues, and describe the new utilities as much faster than the programs they replaced; the same codebase ships in Android and, as of macOS 13, in macOS. It says something about dc’s standing that in the 2020s, multiple actively developed, competing implementations of a 1970 calculator exist.

dc and the Crypto Wars

dc earned an unlikely place in political history in 1995, when cryptographer Adam Back — later known for Hashcash and cited in the Bitcoin whitepaper — compressed a working RSA implementation into a three-line Perl email signature. The Perl merely marshaled data; the arbitrary-precision modular exponentiation at RSA’s core was done by piping a program to dc. Because US export regulations then classified strong cryptography as munitions, the signature (and the T-shirts it was printed on) became a famous act of civil disobedience, demonstrating that a “restricted weapon” fit in a few hundred characters of shell-callable calculator code. Related tricks, such as Diffie–Hellman key exchange written in dc, circulated among cypherpunks during the same export-control debates. The US export rules were substantially relaxed in 1999–2000.

Current Status

dc is alive in the unglamorous way that only bedrock Unix tools are: installed by default or one package away on GNU/Linux, the BSDs, and macOS, exercised daily in shell scripts, and maintained in at least two active implementations (GNU dc and Gavin Howard’s). It was never standardized by POSIX — bc absorbed that role — so portability rests on convention, and small differences exist between implementations (the r swap command and stacked registers, for example, are extensions relative to the oldest versions). There is no official Docker image; none is needed, since dc is present in or trivially added to essentially any Linux container base image via the distribution’s package manager (apt-get install dc on Debian/Ubuntu, for example, or the bc package family elsewhere).

Why dc Matters

dc’s claim on history is threefold. It is a first: the first program on the PDP-11 that Unix grew up on, older than C, present in Unix’s first manual — the oldest surviving Unix language. It is a survivor: fifty-plus years of continuous availability with its core design intact, a longevity almost no software achieves. And it is a miniature masterclass in language design: from a stack, single-character commands, strings, and one execute primitive, it derives conditionals, loops, recursion, and Turing-completeness with no syntax to speak of. Every developer who has piped an impossible-precision calculation through dc -e, and every student who has puzzled out [d1-d1<F*]dsFxp, is touching the same small, sharp tool that Bell Labs used to warm up the machine on which modern computing was built.

Timeline

circa 1970
Bell Labs receives a PDP-11, and dc — written in the B language by Robert Morris and Lorinda Cherry — becomes the first program run on the new machine, before even an assembler was available; Ken Thompson later remarked that dc was the very first program written on the machine
1971
dc(1) is documented in the First Edition Unix Programmer's Manual (dated November 3, 1971) as an "arbitrary precision integer arithmetic package" with stack arithmetic, named registers, and octal input — its BUGS section candidly admits that the remainder operator "doesn't work correctly"
1975
bc ships in Version 6 Unix, written by Lorinda Cherry as an infix, C-like front end that compiles its input into dc programs — dc performs all the actual computation
1979
Seventh Edition Unix documents the mature language in Robert Morris and Lorinda Cherry's paper "DC – An Interactive Desk Calculator"; dc by now supports decimal fractions, strings, executable macros, and conditionals, making it Turing-complete
1991
POSIX standardizes bc, but dc itself is never included in the POSIX standard — it survives instead as a de facto tradition reimplemented on every Unix-like system
Mid-1990s
Ken Pizzini writes GNU dc, an independent reimplementation distributed with Philip Nelson's GNU bc package; in a historical reversal, GNU bc no longer compiles to dc — GNU dc is instead built on bc's arithmetic library
1995
Adam Back condenses RSA encryption into a three-line Perl signature that shells out to dc for its arbitrary-precision modular arithmetic — a celebrated protest against US cryptography export controls, later printed on "munitions" T-shirts
2021
FreeBSD 13.0 replaces its bc and dc utilities with Gavin D. Howard's independent, permissively licensed implementation; the same codebase also ships in Android and, as of macOS 13, in macOS
2025
GNU bc 1.08 is released in early January with GNU dc 1.5.0, adding readline/libedit line editing and an option to disable the shell-escape command in sandboxed environments; point releases follow through May 2025 (dc 1.5.2) — active maintenance more than five decades after dc first ran

Notable Uses & Legacy

PDP-11 bring-up at Bell Labs

Before Unix itself was running on Bell Labs' newly arrived PDP-11 around 1970, dc — cross-compiled from the B language — was used to exercise the machine, making a desk calculator the first program in the lineage that produced Unix and C.

The bc calculator

Traditional Unix bc was not a calculator at all but a compiler: Lorinda Cherry's 1975 front end translated familiar infix expressions and C-like functions into dc programs and piped them to dc, which did all the real arithmetic for a generation of Unix systems.

Adam Back's RSA munitions signature

The famous 1995 "RSA in 3 lines of Perl" email signature — a protest against US export controls that classified strong cryptography as munitions — used dc as its arbitrary-precision engine, piping a dc program that performed the modular exponentiation at the heart of RSA.

Shell scripting on Unix-like systems

Because dc ships in the base system or standard packages of GNU/Linux distributions, the BSDs, and macOS, it remains a lightweight way for shell scripts to do arbitrary-precision arithmetic — computing with hundreds of digits where shell integer arithmetic or floating point would overflow or lose precision.

Language Influence

Influenced

Running Today

Run examples using the official Docker image:

docker pull
Last updated: