Skip to main content

Balanced Ternary Arithmetic

Trits and Bits

A trit (ternary digit) is the fundamental unit of ternary computing. While a binary digit (bit) can represent two states (0 or 1), a trit represents three states. In balanced ternary, these states are {-1, 0, +1}, often written as {T, 0, 1} or {-, 0, +} for brevity.

The information content of a single trit is log2(3) = 1.585 bits. This means each trit carries approximately 58.5% more information than a single bit. To represent the same range of N values, you need ceiling(log3(N)) trits versus ceiling(log2(N)) bits -- fewer symbols, each doing more work.

UnitStatesInformation Content
Bit21.000 bits
Trit31.585 bits

Balanced vs. Unbalanced Ternary

Standard (unbalanced) ternary uses the digit set {0, 1, 2}, analogous to how binary uses {0, 1}. Balanced ternary instead uses {-1, 0, +1}, centering the digit values symmetrically around zero. This seemingly small change has profound consequences:

  • Signed numbers need no special encoding. In binary, representing negative numbers requires conventions like two's complement. In balanced ternary, negative numbers arise naturally -- the number -5 in balanced ternary is simply the negation of +5, obtained by flipping every trit.
  • No wasted representations. Two's complement binary has an asymmetry: an n-bit number can represent one more negative value than positive. Balanced ternary with n trits represents values symmetrically from -(3^n - 1)/2 to +(3^n - 1)/2.
  • Truncation equals rounding. Dropping the least significant trits of a balanced ternary number rounds to the nearest representable value, not toward zero as in binary.

Basic Arithmetic Operations

Ternary Addition

Addition in balanced ternary follows the same column-by-column logic as binary addition, but with three possible values per position. The addition table:

+-10+1
-1-1, carry -1-10
0-10+1
+10+1+1, carry +1

When the sum of two trits exceeds +1 or falls below -1, a carry propagates to the next position. For example, (+1) + (+1) = -1 with a carry of +1 (since 1 + 1 = 2, and 2 in balanced ternary is "1T", meaning +1 in the next position and -1 in the current position).

Ternary Multiplication

Multiplication by a single trit is trivial:

x-10+1
-1+10-1
0000
+1-10+1

This is standard integer multiplication restricted to {-1, 0, +1}:

  • Multiplying by +1 leaves the value unchanged (identity).
  • Multiplying by -1 negates the value (sign flip).
  • Multiplying by 0 produces zero (annihilation).

This property is critical for neural network inference. When model weights are ternary, matrix-vector multiplication reduces to additions and subtractions -- no floating-point multipliers are needed.

Negation

To negate a balanced ternary number, flip the sign of every trit:

  +1  0 -1 +1    (the number +7 in balanced ternary)
-1 0 +1 -1 (the number -7 -- just flip all signs)

This is simpler than binary negation (which requires inverting all bits and adding one) and never produces edge cases or overflow.

Ternary Encoding in Trinity

Trinity represents trits in memory using a compact packed encoding that stores each trit in 2 bits. The mapping is:

Trit Value2-bit Encoding
-1 (T)00
001
+110

This encoding uses 2 bits per trit, achieving an effective density of 1.585 / 2 = 79.3% of the theoretical maximum. While not perfectly optimal (the theoretical minimum is log2(3) = 1.585 bits per trit), the 2-bit encoding enables fast bitwise operations and aligns naturally with byte boundaries.

The HybridBigInt type in Trinity manages this encoding transparently. It maintains two representations: a packed form for memory-efficient storage and an unpacked form (an array of individual trit values) for fast computation. Conversions between the two are performed lazily -- only when needed -- and are cached to avoid redundant work.

With this encoding, a 256-trit vector (a common dimension in Trinity's VSA operations) occupies just 64 bytes in packed form, compared to 256 bytes if each trit were stored in a full byte, or 1024 bytes if stored as 32-bit floats.

Comparison with Binary

PropertyBinaryBalanced Ternary
Digit values{0, 1}{-1, 0, +1}
Info per digit1.000 bits1.585 bits
Radix economy2.885 (94.7%)2.731 (100%)
NegationInvert + add 1Flip all signs
Signed numbersTwo's complementNative
TruncationRounds toward zeroRounds to nearest
MultiplicationFull multiplyAdd/subtract only (for single trit)

Applications in Trinity

The balanced ternary representation is the foundation of every subsystem in Trinity:

  • VSA operations (bind, unbind, bundle) operate element-wise on ternary vectors. Binding uses trit multiplication; unbinding is identical to binding (the operation is its own inverse for non-zero trits).
  • BitNet inference (Firebird) quantizes LLM weights to {-1, 0, +1}, turning matrix multiplications into accumulations.
  • The Ternary VM (VM) executes bytecode with a ternary instruction set, operating on ternary stack values.

Further Reading