Ternary Number Systems
Disclaimer: Nobody but the author endorses the use of the representations described here.
The move to ternary computers requires rethinking such basic issues as the use of radix-complement numbers. 3's complement, for example, has no useful concept of sign bit, while balanced ternary encoding is exactly equivalent to a biased encoding. Floating point representations using balanced ternary are natural, and these encode comfortably in a word composed of 3 9-trit trytes.
A single ternary (base 3) digit is a trit, which may take on the values 0, 1 and 2. Unsigned integers are written in the usual way. Here are some common values in base-3 and decimal:
Just as it is easier for people to use octal (base 8) or hexadecimal (base 16) instead of binary, it is easier to use nonary (base 9) than to use base 3. Nonary numbers group pairs of ternary digits into each digit, but we will generally use. Heptavintimal (base 27) to represent each trybble (3 consecutive trits) with a single character.
5 trits can express a range of values slightly less than can be expressed in 8 bits. Thus, a computer with a 10-trit word would be comparable to a 16-bit minicomputer and a 20-trit word would be comparable to a 32-bit computer. On the other hand, these numbers of trits are "unnatural" in base 3, where 9-trit or 27-trit words make far more sense.
27 is a particularly appealing number, being 3 cubed. A 27-trit word can represent 7,625,597,484,987 distinct values, somewhat under what can be represented in a 44 bit word. In a world where 32-bit words are a bit small but 64 bits seems a bit generous, a move to 27-trit words could well make sense. It is natural to divide this into trytes, the ternary equivalent of bytes. 3 9-trit trytes per word make good sense, where each tryte is divided into 3 trybbles, the tennary equivalent of nybbles.
Floating point numbers can be represented with a 1-tryte exponent followed by a 2-tryte mantissa, giving more than 8 decimal digits of precision. This is enough precision that, for many purposes, there should be little need for double precision. In contrast, classical 32-bit binary floating point representations typically have about 5 decimal digits of precision, not nearly enough for many applications.
A 9-trit tryte seems a bit large for text processing. The classical ASCII character set, for example, encodes only 128 values in 7 bits, while 9 trits allows for 19,683 values. On the other hand, 9 trits allows character sets such as Unicode to be used fairly easily. It is clear, however, that both ASCII and Unicode are strongly biased toward binary encodings, and any ternary computer should use a completely different encoding that is designed in terms of the underlying ternary encoding. The TerSCII character set is an example of such an encoding.
As with binary, there are several approaches to representing negative numbers on a ternary computer. Biased, 2's complement and 3's complement numbers are quite possible. Confining ourselves to 2-trit numbers, the following representations suggest themselves:
|Decimal||Biased||2's C.||3's C.||Bal.|
For all signed ternary number systems except 2's complement, the ranges of values for signed numbers are symmetrical around zero. The range for one trybble is –13 to +13, for one tryte, –9,841 to +9,841, and for one 27-trit word, –3,812,798,742,493 to +3,812,798,742,493.
The negate operation for 3's complement ternary numbers is analogous to the familiar negate operation on 2's complement binary numbers. To negate a 3's complement number, first take the 2's complement of each trit by subtracting it from 2, and then add one to the resulting number. Thus, the 3's complement of 000 is 222+1 or 000, and the three's complement of 111 (representing positive 13) is 111+1 or 112 (representing -13). Unlike the binary system, all ternary numbers have 3's complements because the number range is entirely symmetrical around zero.
Note that the 2's complement of a ternary number is analogous to the 1's complement of a binary number. In each case, each digit is inverted by subtracting from the maximum digit value, one less than the radix. Also, as with 1's complement binary numbers, +0 and –0 are distinct. In three-trit ternary, for example, +0 is 000 and –0 is 222. The ternary value 111 is its own 2's complement, so it has no obvious sign and could therefore be used to represent either the most negative or the most positive number.
Unfortunately, there is no such thing as a sign-trit in any of the ternary number systems. To see if a 3's complement number is negative, strip off all leading 1 trits, and then look at the most significant trit that remains. If it is a 2, the number is negative. Alternatively, for an n-trit 3's complement number, the maximum positive value will be (3n–1)/2. This number will be all ones, for example, 111 representing 13 in 3 trits, or 1111 representing 40 in 4 trits. A number is negative if its value (interpreted as an unsigned value) exceeds this maximum.
Recall that the natural bias for n-bit signed binary number was 2n–1, leading to a trivial relationship between biased and 2's complement numbers: The biased and 2's complement representations are identical, except that the most significant bit of the biased number is the complement of the most significant bit of the 2's complement number. Similarly, the natural bias b for an n-trit ternary number is all ones:
b = ⌊ 3n/2 ⌋ = (3n – 1)/2
Unlike the case in binary, adding the natural ternary bias changes all of the trits, not just the most significant trit.
The biased representation for zero, in any biased number system in any base, is the unsigned representation for the bias. So, a bias of 4 in a ternary machine means that zero is represented as 11, the unsigned ternary representation for 4.
To add two numbers with biased representation, just take the unsigned sum and then subtract the bias. To subtract two biased numbers, take the unsigned difference and then add the bias. If addition is only done to a finite number of trits using an unsigned ternary adder, adding the natural bias to a number is always equivalent to subtracting the bias plus one, and subtracting the bias is always equivalent to adding the bias plus one. That is, for all i:
i + b = i – (b + 1)
i – b = i + (b + 1)
A biased number is negative if its unsigned interpretation is less than the bias. Alternatively, strip off all leading 1 trits and then look at the most significant trit that remains. If it is a zero, the number is negative.
The balanced ternary representation has no analog for even radices such as 2, 8, 10 and 16. Balanced numbers in an odd radix r have digits ranging from –⌊r/2⌋ to +⌊r/2⌋. For ternary, this means that the digit values are –1, 0 and +1 instead of 0, 1 and 2. It is conventional to represent the digit values as - for –1, 0 for zero and + for +1, so the value 2, for example, is represented as +-, that is, +1 in the 3's place and –1 in the 1's place.
Conversion between biased and balanced numbers is quite easy. To convert biased numbers to balanced numbers, subtract 1 from each digit, so 2 becomes +1 (represented as +), 1 becomes 0 (represented as 0), and 0 becomes –1 (represented as -). Conversion in the other direction reverses this. Negating balanced numbers is done by reversing the signs of all of the digits.
This is merely a change of the symbols associated with the digits, a matter of how the digits are printed on the page, not a matter of how the digits are represented inside some mechanism. The difference between biased and balanced representations can be considered to be entirely cosmetic, but thinking in terms of a balanced representaiton may lead to different implementations for arithmetic operations.
The range of values that can be represented by an n-trit balanced ternary number is identical to the range of values that can be represented by an n-trit biased or 3's complement ternary number. Specifically, all of these systems represent numbers in the range from –b to b, inclusive, where b is the natural bias for n trits.
When heptavintimal notation is used, it should always be interpreted as representing the underlying representation interpreted as an unsigned ternary number. This is analogous to the conventions for using hexadecimal on binary computers, where –1 in hexadecimal is typically given as FFFFFFFF and not -1. Given this, along with the equivalence of the balanced and biased ternary number systems, the heptavintimal digit D corresponds to 000 in the balanced system, while 0 correspods to --- and Z corresponds to +++.
Our use of the symbols +, 0 and – to abbreviate +1, 0 and -1 follows [Alexander, 1964], who also concluded that the balanced system was the most appropriate for ternary computing. Here, we reserve judgement about which signed number system is best, but we emphasize that all signed ternary number systems are symmetric around zero (unlike the case when the number base is even). To emphasize this, the following figure shows all combinarions of 3 trits (expressed in unsigned ternary) for comparison with the decimal interpretations in each of the signed number systems discussed above and as well as the simple unsigned interpretation.
Ternary floating point numbers have some useful properties. [Godman and Feldstein, 1974] showed that odd number bases with symmetrical rounding minimize the expected round-off error. [Bustoz, Godman et al, 1979] showed that base 3 is preferred over larger bases.
Given a 27-trit word composed of 3 trytes, it is natural to use one tryte for the exponent followed by a 2-tryte mantissa. Balanced and 3's complement ternary are equally natural choices for both exponent and mantissa; we could even follow the neary universal practice in binary floating point representations and use different systems for the exponent and mantissa. For example we might use a biased or balanced exponent and a 3's complement mantissa. As there is no concept of a sign trit in balanced ternary, we cannot follow the almost-universal convention used on binary computers of separating the sign bit from the rest of the mantissa.
As is done in the binary IEEE flotaing point representation, we will set aside the maximum exponent value to encode values that are "not a number" or NAN. Aside from the representations reserved for undefined and infinite values, other NAN values have no predefined meaning.
The mantissa is represented as a pure fraction strictly less than +1.0 and strictly greater than –1.0. Ternary does not allow anything analogous to a hidden bit, so the point is immediately to the left of the most significant trit of the mantissa. the lack of a hidden bit allows non-normalized values with any exponent, but all arithmetic operations on floating point values should attempt to return normalized results. Thus, when the exponent is greater than balanced --------- or 3's complement 111111112, the most significant trit of the mantissa should be nonzero. For normalized nonzero numbers, therefore, the absolute value of the mantissa is greater than or equal to 1/3. The following pair of tables show the balanced and 3's complement representations of a variety of example values.
|+++++++++ ++++++++++++++++++||ZZZ ZZZZZZ||positive infinity|
|+++++++++ 000000000000000000||ZZZ DDDDDD||undefined|
|+++++++++ ------------------||ZZZ 000000||negative infinity|
|++++++++0 ++++++++++++++++++||ZZX ZZZZZZ||7.4670050 × 104694 = ~1.0 × 39840|
|000000000 +00000000000000000||DDD RDDDDD||0.33333333 = 0.33333333 × 30|
|00000000+ +00000000000000000||DDE RDDDDD||1.00000000 = 0.33333333 × 31|
|00000000+ -00000000000000000||DDE 4DDDDD||–1.0000000 = –0.33333333 × 31|
|--------- 00000000000000000+||000 DDDDDD||1.15225796 × 10–4704 = 3–18 × 3–9841 = 3–9859|
|--------- 000000000000000000||000 DDDDDD||zero|
|111111111 111111111111111111||DDD DDDDDD||positive infinity|
|111111111 000000000000000000||DDD 000000||undefined|
|111111111 111111111111111112||DDD DDDDDE||negative infinity|
|111111110 111111111111111111||DDC DDDDDD||7.4670050 × 104694 = ~1.0 × 39840|
|000000000 100000000000000000||000 900000||0.33333333 = 0.33333333 × 30|
|000000001 100000000000000000||001 900000||1.00000000 = 0.33333333 × 31|
|000000001 200000000000000000||001 K00000||–1.0000000 = –0.33333333 × 31|
|111111112 000000000000000001||DDE 000001||1.15225796 × 10–4704 = 3–18 × 3–9841 = 3–9859|
|111111112 000000000000000000||DDE 000000||zero|
To convert an 18 trit balanced ternary integer to balanced floating point, just attach an exponent of +18 (decimal) which is 00000+-00 (ternary) or DE4 (heptavintimal), and then normalize.
To convert an 18-trit 3's complement integer to 3's complement floating point, just attach an exponent of +18 (decimal) which is 000000200 (ternary) or 00K (heptavintimal), and then normalize.