Computing History · Early Computing

Relay Arithmetic and the Floating-Point Word in the Zuse Z3

How a two-register stack machine with a 22-bit floating-point word ran at a few hertz, why it had no conditional branch, and what that costs in program length.

The Z3 arithmetic unit is 22 bits wide, and those bits do not hold an integer. Konrad Zuse designed the machine in 1938 and completed it in Berlin in 1941 with 2,600 relays; its word is binary floating point, split into 1 sign bit, 7 exponent bits and 14 mantissa bits. Zuse’s technical page records the unit as 22-bit binary floating point with addition, subtraction, multiplication, division and square root, plus an arithmetic exception handler. What the machine could represent, how long an operation took, and how much of a program had to be settled before the film was punched follow from those 22 bits and from relay speed.

The field split, and what each field buys

The mantissa field sets the resolution. Fourteen bits encode at most 2^14 = 16,384 distinct significands, between 3.9 and 4.2 significant decimal digits depending on whether the leading bit of a normalised value occupies a bit of the field or is implied. A constant typed as 3.14159 arrives with its last one or two digits set by rounding, and no source summarised here states the rounding rule.

The exponent field sets the range. Seven bits give 128 values, spanning at most 127 intervals, so the largest representable magnitude exceeds the smallest by no more than 2^127, near 1.7 × 10^38, or about 38 decimal decades. That bound holds under any encoding. Where the window sits on the number line depends on how the field is interpreted, and the sources give no bias, so the absolute limits are not fixed by the documented facts.

Memory is 64 words of 22 bits, 1,408 bits or 176 bytes, addressed by six bits. Constants came in on a decimal keyboard and were converted on entry, so the mantissa limit applied to every input before the first instruction ran.

MANT_BITS, EXP_BITS = 14, 7
WORD_BITS = 1 + EXP_BITS + MANT_BITS               # 22

def pack(x, exponent):
    """Model of the documented field split, not a simulation of Z3 arithmetic.
    Mantissa is truncated; the rounding rule here is the model's own choice."""
    if x == 0:
        return 0
    sign, m = (1 if x < 0 else 0), abs(x)
    while m >= 1.0:
        m, exponent = m / 2.0, exponent + 1
    while m < 0.5:
        m, exponent = m * 2.0, exponent - 1
    mant = int(m * (1 << MANT_BITS)) & ((1 << MANT_BITS) - 1)
    return (sign << 21) | ((exponent & 0x7F) << 14) | mant

def fields(word):
    return (word >> 21) & 1, (word >> 14) & 0x7F, (word & 0x3FFF) / (1 << 14)

print(WORD_BITS)                                       # 22
print(fields(pack(1.0, 0)))                            # (0, 1, 0.5)
print(f"relative step  {2.0 ** -13:.3e}")              # 1.221e-04
print(f"decimal digits {13 * 0.30103:.2f}")            # 3.91
print(f"exponent span  {2.0 ** 127:.3e}")              # 1.701e+38

The block reproduces the arithmetic of the format and nothing else. It normalises into [0.5, 1) and stores the leading bit explicitly, the coarser convention, so the relative step at the bottom of a binade is 2^-13 and the exponent is a raw 7-bit field with no bias. Whether the machine used that convention is separate from the field widths.

Why four decimal digits force the problem to be scaled first

Floating point buys range at the cost of a fixed relative error, set here by the mantissa width. Scaling is not a matter of taste: every problem has to be arranged so the differences of interest sit well above the noise floor of the largest intermediate. Subtract two numbers near 1 that agree to four decimal places and the result is zero, not small. The information was never in the word.

Accumulation is the other exposure. Each addition rounds to the mantissa width, and a worst-case bound on n additions is n times one relative step of 2^-13 if every rounding falls the same way. A thousand-term sum reaches about 12 percent by that bound, which is a bound rather than an observation.

The constraint shapes the workload. A 64-word store cannot hold a large system, and four digits cannot resolve one whose coefficients differ by six orders of magnitude, so the machine suited small computations normalised by hand: linear systems, polynomial evaluations, engineering formulae whose variables had been put into comparable units.

Relay cycles set the price of each operation

The technical page records average calculation speed as 0.8 seconds for addition and 3 seconds for multiplication, with the relay clock at 5.3 Hz. Rojas’s architectural analysis gives multiplication as 16 cycles. The three numbers can be checked against one another, and the check is arithmetic rather than measurement: 16 cycles at 5.3 Hz is 3.02 seconds, matching the stated multiplication time, and 0.8 seconds corresponds to about 4.2 cycles. The ratios, 16 to 4.2 and 3 to 0.8, both say multiplication cost about four additions.

Division and square root are documented operations whose cycle counts the sources do not give; the safe assumption is only that each costs more than a multiplication. A faster Z3 would have needed faster relays or fewer cycles per operation, and 5.3 Hz is the limit of the components available.

One addition per 0.8 seconds is 1.25 per second, and ten thousand operations at that rate is 8,000 seconds, a little over two hours. The valve machine built for one cryptanalytic job in the same war is the contrast: its speed came from electronic switching, and no arrangement of relays could close that gap.

Two registers and a one-bit load target

The control rules reported by Rojas describe a stack two words deep. The first load places a memory word in R1; the next load places a word in R2; an arithmetic instruction consumes both and leaves its result in R1 with R2 cleared. A store writes R1 to memory and clears R1. A display instruction shows R1 and clears R2. The asymmetry in the last rule fits the rest: the register cleared is the one the next load will fill.

As a state machine the rules need one bit of bookkeeping, because at most one register is empty at a time. A load targets the empty register, and every instruction that consumes or writes clears exactly one, so the alternation is forced rather than chosen.

With no instruction that adds a memory word directly to a register, both operands of every arithmetic instruction must already be in R1 and R2, and a third value in an expression has nowhere to go. Evaluation order is fixed by the register file: compute a subexpression, store it, load the next operand, compute, store again. Instruction count grows with the nesting depth of the expression, not merely with the number of operations. A three-address machine would need more relays; the two-register arrangement spends program length instead, and on punched film that was the cheaper resource.

Film, fixed loops, and the branch that was never built

The program sat outside the machine on punched film, so changing a program meant punching new film rather than rewiring. That separation is the one Babbage pursued with card-driven control on the Analytical Engine, where the operation sequence lived on a chain of cards rather than inside the mechanism.

Loops could be built, but only as repetition. A loop is a section of film read more than once, so its iteration count is fixed when the film is punched. There was no conditional branch instruction. Every run-time decision had to be made by whoever prepared the film: how many terms of a series to evaluate, how many refinement steps a numerical method gets, which of two formulas applies to the data. A routine that would today test for convergence and stop was written to run a fixed number of steps and accept the accuracy that produced.

The absence is a hardware consequence rather than an oversight. A conditional branch needs a comparison and a change of the next-instruction address, and both cost relays in a machine already spending 2,600 of them on arithmetic, storage and control. The documented exception handler addresses the neighbouring problem: the arithmetic can produce plus infinity, minus infinity and undefined, and those values pass through later operations. An error state therefore has to be a value the arithmetic will accept, because a trap demanding a decision could not be taken. Representing the exceptional values in the word is the cheapest error handling available with no control flow.

Speculative execution and the limit of the 1998 result

Rojas showed in 1998 how to implement a universal Turing machine on the Z3. The construction does not add a branch instruction. It makes the program long enough to compute every possible branch and cancel the results the branch would have discarded: all paths are evaluated and the unneeded ones annihilated afterwards.

Cancellation is expressible with the documented instruction set. Selecting between two computed values a and b needs a mask m that is 0 or 1, and a × m + b × (1 − m) yields the chosen one using only multiplication and addition. The mask has to be produced by arithmetic on the operands, since nothing in the instruction set compares and branches, and that is where the construction spends its instructions. Nothing in it requires control flow, only that both sides be computed first.

The cost is exponential in the number of decisions: k independent binary choices need 2^k evaluations. Twenty choices is 1,048,576 times the work, and a hundred-operation computation becomes 10^8 operations, which at 0.8 seconds per addition is roughly 2.5 years of machine time. That figure is arithmetic illustration, not a measurement of anything that ran. It explains why the result is a theorem about computability rather than a description of use: the film length required grows without bound as branches multiply, and film is a physical object. Both halves of the claim hold at once. A universal machine can be encoded on the Z3, and the Z3 could not be used as one.

The raid, the replica, and a claim with limits

The original Z3 was destroyed on 21 December 1943 in an Allied bombing raid on Berlin. A functioning replica built in 1961 is displayed in the Deutsches Museum in Munich.

The Z3 is often called the first working programmable, fully automatic digital computer, and that claim needs its limits. The machine was electromechanical, not electronic. It had no conditional branch. It was not put into everyday operation. Electronic machines came later, and the priority question, including the broader suggestion that Zuse invented the computer, is contested and treated at length in Rojas and Hashagen’s volume rather than settled by one machine. What the Z3 supports without dispute is narrower: a floating-point arithmetic unit built from relays, a word format in which range and precision were explicit design variables, and a program held outside the machine.

References

  1. Z3 technical data — Horst Zuse, Zuse archive
  2. Konrad Zuse's Legacy: The Architecture of the Z1 and Z3 — Raul Rojas; IEEE Annals of the History of Computing, Vol. 19 No. 2, 1997
  3. How to Make Zuse's Z3 a Universal Computer — Raul Rojas; IEEE Annals of the History of Computing, Vol. 20 No. 3, 1998
  4. The First Computers: History and Architectures — Raul Rojas and Ulf Hashagen (eds.); MIT Press, 2000