balanced-ternary
A pure-Python implementation of balanced ternary arithmetic. The BalancedTernary
type uses digits from the set {-1, 0, 1}, writes -1 as T in T-notation, and
implements addition and multiplication at the digit level with balanced-ternary
carry logic -- not by converting to int and back.
What is balanced ternary?
Balanced ternary is a non-standard positional numeral system where each digit
(trit) is one of {-1, 0, 1}. The value -1 is conventionally written as T.
The value of a balanced ternary numeral is the sum of each digit times its
corresponding power of 3.
"1TT" = 1*9 + (-1)*3 + (-1)*1 = 9 - 3 - 1 = 5
"T1T" = (-1)*9 + 1*3 + (-1)*1 = -9 + 3 - 1 = -7
"1T" = 1*3 + (-1)*1 = 3 - 1 = 2
Every integer has a unique balanced ternary representation, and negation is exact -- just flip the sign of every digit.
Installation
pip install balanced-ternary
Or with uv:
uv add balanced-ternary
Quick start
from balanced_ternary import BalancedTernary
# Convert from int
a = BalancedTernary.from_int(5)
print(a.to_str()) # "1TT"
# Convert from T-notation string
b = BalancedTernary.from_str("1T")
print(b.to_int()) # 2
# Arithmetic (digit-level carry logic)
print((a + b).to_int()) # 7
print((a - b).to_int()) # 3
print((a * b).to_int()) # 10
# Negation is exact -- just flip digit signs
print((-a).to_str()) # "T11" (-5 in balanced ternary)
# T-notation input supports lowercase t
c = BalancedTernary.from_str("1t0T")
print(c.to_int()) # 23
# Ordering: compare and sort by integer value
x = BalancedTernary.from_int(3)
y = BalancedTernary.from_int(7)
print(x < y) # True
print(x >= y) # False
values = [BalancedTernary.from_int(n) for n in [5, -2, 0, 3]]
print([v.to_int() for v in sorted(values)]) # [-2, 0, 3, 5]
# Floored division and modulo (Python semantics: remainder has sign of divisor)
d = BalancedTernary.from_int(7)
e = BalancedTernary.from_int(2)
print((d // e).to_int()) # 3
print((d % e).to_int()) # 1
q, r = divmod(d, e)
print(q.to_int(), r.to_int()) # 3 1
# Negative divisor: remainder is non-positive (Python floored convention)
f = BalancedTernary.from_int(-2)
print((d // f).to_int()) # -4
print((d % f).to_int()) # -1
API
BalancedTernary.from_int(value: int) -> BalancedTernary
Convert any Python int to balanced ternary.
BalancedTernary.from_str(text: str) -> BalancedTernary
Parse a T-notation string. Valid characters are 0, 1, T, t. The
string is most-significant-first. Raises ValueError on empty input or
invalid characters.
to_int() -> int
Return the integer value.
to_str() -> str
Return the canonical T-notation string (most-significant-first, no leading zeros except for the value zero itself).
Operators
| Operator | Meaning |
|---|---|
+ |
Addition |
- |
Subtraction |
* |
Multiplication |
// |
Floored integer division |
% |
Floored modulo (remainder sign matches divisor) |
divmod() |
Returns (quotient, remainder) as BalancedTernary values |
unary - |
Negation (exact, no carry needed) |
== |
Equality |
<, <=, >, >= |
Ordering by integer value (sortable) |
hash() |
Hashable (usable as dict key) |
repr() |
BalancedTernary.from_str('...') |
str() |
T-notation string |
Division sign convention: // and % follow Python's floored division: the
remainder always has the same sign as the divisor. For example, (-7) // 2 == -4
and (-7) % 2 == 1. __truediv__ (/) is intentionally omitted -- BalancedTernary
is an exact integer type and true division would break the exact-arithmetic contract
for most operand pairs.
Digit-level carry logic
When adding two balanced-ternary digits plus a carry, the column sum s is
mapped as follows:
| s | result digit | carry out |
|---|---|---|
| -3 | 0 | -1 |
| -2 | 1 | -1 |
| -1 | -1 | 0 |
| 0 | 0 | 0 |
| 1 | 1 | 0 |
| 2 | -1 | 1 |
| 3 | 0 | 1 |
Multiplication uses digit-by-digit partial products accumulated with the addition logic above.
Development
git clone https://github.com/amaar-mc/balanced-ternary
cd balanced-ternary
uv pip install -e ".[dev]"
uv run pytest -q
uv run ruff check .
uv run mypy src
License
MIT. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file balanced_ternary-0.2.0.tar.gz.
File metadata
- Download URL: balanced_ternary-0.2.0.tar.gz
- Upload date:
- Size: 793.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
752d72f9fa1f7a2e77416c0497eddae4527062d5e9374eb983812227beeac8f9
|
|
| MD5 |
a189f09dac647ffa6f01921feaf28f57
|
|
| BLAKE2b-256 |
ba67851badf25fb0603665b68f9b3c32a6c900826d33d6c4f5959269928aa152
|
File details
Details for the file balanced_ternary-0.2.0-py3-none-any.whl.
File metadata
- Download URL: balanced_ternary-0.2.0-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c1cb44d14ce533fec3912cfa863ee6ee7a8f237c6fa9e7c6463b2cc83cdcff8
|
|
| MD5 |
44758872cfe7e4143c150c6df8ab9775
|
|
| BLAKE2b-256 |
ea97c7f52ed4c77e6ec0b5595885610100c9c09e170376679c0edc0c11f2190f
|