Est. 1971 Intermediate

dc

The oldest surviving Unix language — a stack-based, arbitrary-precision desk calculator using reverse Polish notation, first shipped with Version 1 AT&T Unix in 1971.

Created by Robert Morris and Lorinda Cherry

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

dc (desk calculator) holds a singular place in computing history: it is the oldest surviving Unix language program. First shipped with Version 1 AT&T Unix on November 3, 1971, dc predates the C programming language, the Bourne shell, and nearly every other tool still in common use on Unix-like systems. More than fifty years later, dc remains available on virtually every Unix, Linux, and macOS installation.

History & Origins

dc was created by Robert Morris and Lorinda Cherry at AT&T Bell Laboratories. Morris, an American cryptographer and mathematician who joined Bell Labs in 1960, contributed several foundational Unix components including the math library, the crypt program, and the Unix password encryption scheme. Cherry joined Bell Labs’ Computing Science Research Center in 1971 and collaborated with Morris on dc.

The original implementation of dc was written in B, the programming language that preceded C at Bell Labs. According to Ken Thompson, dc was reportedly the first program to run on Bell Labs’ PDP-11 — even before an assembler was available for the machine. Later versions of dc were rewritten, first in PDP-11 assembly language (as seen in the Version 6 Unix source tree), and eventually in C.

The Birth of bc

In 1975, Lorinda Cherry created bc (bench calculator) as a front-end to dc. Where dc uses reverse Polish notation, bc provides a more conventional infix syntax resembling the C programming language. The original bc was literally a preprocessor: it compiled its C-like input into dc commands and piped the results through dc for execution. This architectural relationship persisted for many years, though modern implementations (such as GNU bc and Gavin Howard’s implementation) have reversed or eliminated this dependency.

Design Philosophy

dc embodies the Unix philosophy of small, sharp tools. Its interface is minimal — most commands are single characters — and it communicates through standard input and output, making it composable with other Unix utilities via pipes.

The core design is built on three concepts:

  1. Reverse Polish Notation (RPN): Operators follow their operands, eliminating the need for parentheses and operator precedence rules
  2. Stack-based computation: All values are pushed onto a stack; operations consume values from the stack and push results back
  3. Arbitrary precision: dc supports unlimited precision arithmetic, with the number of fractional digits controlled by the user

This design makes dc simultaneously powerful and cryptic. A simple addition looks like:

3 4 + p

This pushes 3 and 4 onto the stack, adds them, and prints the result (7). The p command prints the top of the stack without removing it.

Key Features

Arbitrary-Precision Arithmetic

dc performs arithmetic to arbitrary precision. The k command sets the number of fractional digits maintained during computation. By default, precision is zero, meaning dc performs integer arithmetic:

10 k
1 3 / p

This sets precision to 10 decimal places, divides 1 by 3, and prints .3333333333.

Registers and Storage

dc provides at least 256 named registers, each identified by a single character. Each register maintains its own stack, allowing values to be stored and retrieved:

5 sa    # Store 5 in register 'a'
la p    # Load from register 'a' and print

Strings and Macros

dc can manipulate strings as well as numbers. Strings are enclosed in square brackets and can be printed or — crucially — executed as macros. This capability transforms dc from a simple calculator into a programmable system:

[Hello, World!] p

Conditional Execution

dc supports conditional execution by comparing the top two stack values and executing a macro stored in a register if the condition is met:

# Print "yes" if 5 > 3
5 3 [yes] sa >a

The >a command pops two values, compares them, and executes the macro in register a if the first is greater than the second.

Base Conversion

dc supports separate input and output radices, making base conversion straightforward:

16 o 255 p    # Set output radix to 16, print 255 → FF
16 i FF p     # Set input radix to 16, print FF → 255

Looping via Recursion

Since dc has no built-in loop constructs, loops are implemented through recursive macros:

# Count from 1 to 10
[p 1 + d 10 !<a] sa 1 la x

This stores a macro in register a that prints the top of the stack, increments it, duplicates it, and recursively calls itself while the value is not greater than 10.

Implementations

dc has been independently implemented multiple times over its long history:

ImplementationPlatformNotes
GNU dcLinux, cross-platformPart of the GNU bc package; latest version 1.5.2 (2025)
OpenBSD dcOpenBSDComplete rewrite by Otto Moerbeek (2003, OpenBSD 3.3) using big number routines
Gavin Howard’s dcmacOS, FreeBSD, AndroidModern BSD-licensed implementation; default on macOS since Ventura (2022)
Plan 9 dcPlan 9Maintained as part of the Plan 9 operating system

Installing dc

On most Unix-like systems, dc is already installed. If not:

1
2
3
4
5
6
7
8
# Debian/Ubuntu
sudo apt install dc

# Alpine Linux
apk add bc

# macOS — pre-installed
dc

Current Relevance

Despite its age and terse syntax, dc remains relevant for several reasons:

  • Ubiquity: dc is available on essentially every Unix-like system, making it one of the most portable tools for arithmetic in shell scripts
  • Arbitrary precision: Unlike most shell arithmetic (which is limited to integer or floating-point precision), dc handles numbers of any size with any desired precision
  • No dependencies: dc requires nothing beyond a basic Unix installation, making it valuable for minimal environments, containers, and recovery scenarios
  • Pipeline integration: dc reads from standard input, making it trivially composable with other Unix tools

POSIX Status

Notably, dc is not part of the POSIX standard. When POSIX standardized bc in 1992 (IEEE Std 1003.2), dc was deliberately excluded because bc was considered to have “a more intuitive programmatic interface.” Despite this, dc is shipped on virtually every Unix-like system in practice.

Why It Matters

dc’s significance extends beyond its utility as a calculator. As the oldest surviving Unix language program, it represents the dawn of the Unix tool philosophy — small programs that do one thing well, communicate through text streams, and compose together into larger solutions.

The dc-to-bc relationship also demonstrates an important pattern in language design: building a more user-friendly language as a front-end to a more powerful but less accessible one. This architectural approach — where a high-level language compiles down to a lower-level execution engine — anticipates patterns seen throughout computing, from compiled languages targeting virtual machines to modern transpilers.

dc is a living artifact of Unix history, still doing exactly what it was designed to do more than fifty years ago.

Timeline

1971
dc appears in Version 1 AT&T Unix (November 3, 1971), created by Robert Morris and Lorinda Cherry at Bell Labs
1971
dc reportedly becomes the first program to run on Bell Labs' PDP-11, before even an assembler was available
1975
Lorinda Cherry creates bc as a front-end preprocessor to dc; both ship with Version 6 Unix
1991
Philip A. Nelson releases GNU bc, which includes GNU dc as a companion tool
2003
OpenBSD 3.3 includes a complete rewrite of dc by Otto Moerbeek using big number routines
2025
GNU dc 1.5.0 released with readline/libedit support and new recursion limit options

Notable Uses & Legacy

Unix Shell Scripting

dc is commonly used in shell scripts for arbitrary-precision arithmetic and base conversions, especially on minimal systems where more complex tools may not be available

System Administration

Used for quick command-line calculations, hexadecimal/octal/decimal conversions, and computing network addresses or file sizes

Code Golf

dc's extremely terse single-character command syntax makes it a popular choice in code golf competitions and programming puzzles

Portable Scripting

dc is available on virtually every Unix-like system, making it a reliable tool for arithmetic in scripts that must run across diverse environments

Language Influence

Influenced By

Reverse Polish Notation

Influenced

Running Today

Run examples using the official Docker image:

docker pull alpine:latest

Example usage:

echo '2 3 + p' | docker run --rm -i alpine:latest sh -c 'apk add --quiet bc > /dev/null && dc'
Last updated: