Число, у которого порядок — четыре трита
Вы узнаете
Как TNF17e упаковывает знак, тернарный порядок и мантиссу в 17 бит и почему 17, а не 16.
Имя TNF носят две разные вещи. В решете TNF(k, b) — алфавит весов с 3 или 9 уровнями. TNF17e в tnf17.t27 — Ternary Network Float, который спека называет знаковым форматом накопителя: бит знака, 7-битное смещение и 9-битная мантисса, а значение равно (-1)^s x (1 + m/512) x 2^(offset - 40). Его триты стоят в порядке, а не в весах: смещение принимает 81 значение, ровно 3^4, так что порядок — это четыре сбалансированных трита, от -40 до +40. Четыре трита стоят 7 бит на двоичном чипе, поэтому ступень занимает 17 бит, а не 16; спека записывает, что её источник считал позиции, а трит — не бит. Браузер выполняет 20 из 44 проверок, в том числе все 10 инвариантов, и у каждого пропуска называет приведение типа, которое не смог вычислить.
Попробуйте
Прочитайте причину у одного пропущенного теста; затем найдите инвариант, который говорит, что четыре трита дают 81 значение. В спеке у tnf16 тоже четыре трита порядка и сумма 16: найдите width_rule и прочитайте, что считает это 16 — биты или позиции.

TNF17e as a t27 spec: a sign, a 7-bit offset holding four balanced trits, a 9-bit mantissa, compiled by t27c in your browser. Seven backends; every test the page cannot run says why.
specs/numeric/tnf16.t27
// SPDX-License-Identifier: Apache-2.0
// tnf16.t27 -- TNF16: Ternary Network Float.
//
// A fixed-field GoldenFloat whose EXPONENT is a balanced-ternary number, built to
// beat tekum16 on a ternary fabric: no regime decode (tekum16's main cost), the
// exponent is added natively in balanced ternary, and the mantissa keeps GF16's
// phi-optimal uniform 9-bit precision (vs tekum16 tapering to ~4 bits at extremes).
//
// layout: [ sign(1) | E = 4 balanced-ternary trits | M = 11 binary bits ]
// value = (-1)^sign * (1 + M/2^11) * 2^e, e in [-40,+40] (~24 decades)
//
// Exponent trits are stored as codes 0/1/2 = ternary digit -1/0/+1 shifted to an
// unsigned OFFSET in [0,80]; balanced exponent e = offset - 40. Measured (session
// 2026-08-05): beats tekum16 3x at mid range and 5.5x at far range, 0 clipping.
// phi^2 + 1/phi^2 = 3 | TRINITY
module triformat_tnf16 {
use base::types;
const SIGN_BITS: u32 = 1;
const EXP_TRITS: u32 = 4; // 3^4 = 81 exponent values
const MANT_BITS: u32 = 11; // 1 + E_t + M = 16, the ladder's width rule
const EXP_OFFSET: u32 = 40; // (3^EXP_TRITS - 1) / 2 -- the balanced zero point
const OFFSET_MAX: u32 = 80; // 3^EXP_TRITS - 1
// Decode the 4-trit exponent field (each 2-bit code in {0,1,2}) into its
// unsigned offset in [0,80]: offset = t0 + 3*t1 + 9*t2 + 27*t3.
fn exp_offset(t0: u32, t1: u32, t2: u32, t3: u32) -> u32 {
return t0 + (3 * t1) + (9 * t2) + (27 * t3);
}
// The balanced exponent value is (offset - EXP_OFFSET), kept as a biased u32
// (add EXP_OFFSET back so it stays unsigned): biased_exp == offset.
// Reserved: offset == OFFSET_MAX is the special (inf/nan) row.
fn is_finite(offset: u32) -> bool {
return offset != OFFSET_MAX;
}
// Number of representable exponent steps (3^EXP_TRITS).
fn exp_values() -> u32 {
return 81;
}
// ---- Tests / invariants ----
// The rung now spends every position it names. This is why the change was
// made, and the guard against it regressing.
test width_rule {
assert(SIGN_BITS + EXP_TRITS + MANT_BITS == 16, "1 + E_t + M = N, one position per trit");
}
// The all-max trit word is the top of the offset range (= +40 before reserve).
test offset_range {
assert(exp_offset(0, 0, 0, 0) == 0, "min offset (exponent -40)");
assert(exp_offset(2, 2, 2, 2) == 80, "max offset (reserved special)");
assert(exp_offset(1, 1, 1, 1) == 40, "center offset = exponent 0 (unity)");
}
// Radix-3 economy: 4 trits carry 81 exponent values (~24 decades) with no
// regime decode -- more range per digit than a 4-bit binary exponent (16).
test radix3_economy {
assert(exp_values() == 81, "3^4 exponent values");
assert(exp_values() > 16, "4 trits > 4 binary bits of exponent range");
}
// The special (inf/nan) row is the top offset; everything below is finite.
test finiteness {
assert(is_finite(40) == true, "unity exponent is finite");
assert(is_finite(79) == true, "near-top finite");
assert(is_finite(80) == false, "offset 80 is the reserved special row");
}
}
Все уроки
Модуль 1 · Лаборатория: наши исследования
Свой формат чисел, честная таблица результатов и таблицы модели, перемноженные на плате.
Модуль 2 · ИИ-числа: блок MX
Как ИИ-чипы хранят веса в нескольких битах: один общий масштаб на блок, сам байт масштаба и что один выброс делает с соседями.
Модуль 3 · Тернарные веса
Веса, которые бывают только минус масштаб, ноль или плюс масштаб, пять правил, которые должен пройти тернарный алфавит, и прогон тестов, который ничего не проверил.
Модуль 4 · Тернарный формат Ternary Network Float
Правило, которое компилятор проверяет до запуска любого теста, и 17-битное число с плавающей точкой, порядок которого — четыре сбалансированных трита.
Модуль 5 · Арифметика чисел со знаком
Умножить два числа со знаком, сложить их, когда знаки разные, и сделать то и другое сразу в умножении с накоплением.
Модуль 6 · Части нейрона
ReLU с изломом в нуле, степень двойки для softmax и argmax, который называет ответ.
Модуль 7 · Обучение на ошибке
Потеря, которая оценивает неверную догадку в битах, один шаг, который сдвигает вес против градиента, и скрытый слой, который нужен XOR.
Модуль 8 · BitNet: тернарные сети
Порог, который сжимает сумму обратно до трёх значений, один нейрон, который становится другой функцией при смене весов, и нейрон, который читает входы по 27 тритов за раз.
Модуль 9 · Тернарный MAC как чип
Скалярное произведение 27 тритов как провода без регистра, та же сумма, которую регистр копит на каждом такте, и небольшая целая сеть в конце курса.