Solución:
Si lo está haciendo con una computadora, las cosas ya están en binario, por lo que dividir repetidamente por 3 y tomar los restos es tan fácil como las cosas.
Si lo hace a mano, la división larga en binario funciona igual que la división larga en decimal. simplemente divida por tres y tome el resto. si empezamos con 16
___101
11 |10000
11
100
11
1
100000 / 11 = 101 + 1/11 so the least significnnt digit is 1
101/ 11 = 1 + 10/11 the next digit is 2
1 and the msd is 1
entonces en ternario 121
Puede utilizar algunas abreviaturas inteligentes para convertir. El siguiente código es la dirección “incorrecta”, es una conversión de ternario a binario basada en el hecho de que 3 ^ 2 = 2 ^ 3 + 1 usando solo suma binaria. Básicamente, estoy convirtiendo dos dígitos ternarios en tres dígitos binarios. De binario a ternario sería un poco más complicado, ya que se requeriría la suma ternaria (y probablemente la resta) (trabajando en eso). Asumo el dígito menos significativo en la cabeza de la lista (que es la única forma que tiene sentido), por lo que tienes que leer los números “al revés”.
addB :: BNumber → BNumber → BNumber
addB a [] = a
addB [] b = b
addB (B0:as) (B0:bs) = B0 : (addB as bs)
addB (B0:as) (B1:bs) = B1 : (addB as bs)
addB (B1:as) (B0:bs) = B1 : (addB as bs)
addB (B1:as) (B1:bs) = B0 : (addB (addB as bs) [B1])
t2b :: TNumber → BNumber
t2b [] = []
t2b [T0] = [B0]
t2b [T1] = [B1]
t2b [T2] = [B0,B1]
t2b (T2:T2:ts) = let bs = t2b ts in addB bs (B0:B0:B0:(addB bs [B1]))
t2b (t0:t1:ts) =
let bs = t2b ts
(b0,b1,b2) = conv t0 t1
in addB bs (b0:b1:b2:bs)
where conv T0 T0 = (B0,B0,B0)
conv T1 T0 = (B1,B0,B0)
conv T2 T0 = (B0,B1,B0)
conv T0 T1 = (B1,B1,B0)
conv T1 T1 = (B0,B0,B1)
conv T2 T1 = (B1,B0,B1)
conv T0 T2 = (B0,B1,B1)
conv T1 T2 = (B1,B1,B1)
[Edit] Aquí está la dirección binaria a ternaria, como se esperaba un poco más larga:
addT :: TNumber → TNumber → TNumber
addT a [] = a
addT [] b = b
addT (T0:as) (T0:bs) = T0 : (addT as bs)
addT (T1:as) (T0:bs) = T1 : (addT as bs)
addT (T2:as) (T0:bs) = T2 : (addT as bs)
addT (T0:as) (T1:bs) = T1 : (addT as bs)
addT (T1:as) (T1:bs) = T2 : (addT as bs)
addT (T2:as) (T1:bs) = T0 : (addT (addT as bs) [T1])
addT (T0:as) (T2:bs) = T2 : (addT as bs)
addT (T1:as) (T2:bs) = T0 : (addT (addT as bs) [T1])
addT (T2:as) (T2:bs) = T1 : (addT (addT as bs) [T1])
subT :: TNumber → TNumber → TNumber
subT a [] = a
subT [] b = error "negative numbers supported"
subT (T0:as) (T0:bs) = T0 : (subT as bs)
subT (T1:as) (T0:bs) = T1 : (subT as bs)
subT (T2:as) (T0:bs) = T2 : (subT as bs)
subT (T0:as) (T1:bs) = T2 : (subT as (addT bs [T1]))
subT (T1:as) (T1:bs) = T0 : (subT as bs)
subT (T2:as) (T1:bs) = T1 : (subT as bs)
subT (T0:as) (T2:bs) = T1 : (subT as (addT bs [T1]))
subT (T1:as) (T2:bs) = T2 : (subT as (addT bs [T1]))
subT (T2:as) (T2:bs) = T0 : (subT as bs)
b2t :: BNumber → TNumber
b2t [] = []
b2t [B0] = [T0]
b2t [B1] = [T1]
b2t [B0,B1] = [T2]
b2t [B1,B1] = [T0,T1]
b2t (b0:b1:b2:bs) =
let ts = b2t bs
(t0,t1) = conv b0 b1 b2
in subT (t0:t1:ts) ts
where conv B0 B0 B0 = (T0,T0)
conv B1 B0 B0 = (T1,T0)
conv B0 B1 B0 = (T2,T0)
conv B1 B1 B0 = (T0,T1)
conv B0 B0 B1 = (T1,T1)
conv B1 B0 B1 = (T2,T1)
conv B0 B1 B1 = (T0,T2)
conv B1 B1 B1 = (T1,T2)
[Edit2] Una versión ligeramente mejorada de subT que no necesita addT
subT :: TNumber → TNumber → TNumber
subT a [] = a
subT [] b = error "negative numbers supported"
subT (a:as) (b:bs)
| b ≡ T0 = a : (subT as bs)
| a ≡ b = T0 : (subT as bs)
| a ≡ T2 ∧ b ≡ T1 = T1 : (subT as bs)
| otherwise = let td = if a ≡ T0 ∧ b ≡ T2 then T1 else T2
in td : (subT as $ addTDigit bs T1)
where addTDigit [] d = [d]
addTDigit ts T0 = ts
addTDigit (T0:ts) d = d:ts
addTDigit (T1:ts) T1 = T2:ts
addTDigit (t:ts) d = let td = if t ≡ T2 ∧ d ≡ T2 then T1 else T0
in td : (addTDigit ts T1)
Creo que a todo el mundo le falta algo importante. Primero, calcule una tabla de antemano, para cada bit binario, necesitamos la representación en ternario. En MATLAB, lo había construido así, aunque todos los pasos posteriores se realizarán puramente a mano, el cálculo es muy fácil.
dec2base(2.^(0:10),3)
ans =
0000001
0000002
0000011
0000022
0000121
0001012
0002101
0011202
0100111
0200222
1101221
Ahora, considere el número binario 011000101 (que resulta ser el número decimal 197, como veremos más adelante). Extraiga la representación ternaria para cada bit binario de la tabla. Escribiré las filas correspondientes.
0000001
0000011
0002101
0011202
Ahora solo suma. Obtenemos esta representación, en ternario no llevado.
0013315
Sí, esos no son números ternarios, pero están casi en una representación de base 3 válida. Ahora todo lo que necesitas hacer es hacer los acarreos. Comience con el dígito de las unidades.
5 es mayor que 2, así que reste el número de múltiplos de 3 e incremente el segundo dígito del resultado según corresponda.
0013322
El segundo dígito ahora es un 2, un dígito ternario legal, así que pase al tercer dígito. Haz eso también
0014022
Finalmente produciendo el número ternario ahora completamente válido …
0021022
¿Fueron correctos mis cálculos? Dejaré que MATLAB haga el juicio final por nosotros:
base2dec('011000101',2)
ans =
197
base2dec('0021022',3)
ans =
197
¿He señalado cuán trivial era esta operación, que podía hacer la conversión completamente a mano, yendo esencialmente directamente de binario a ternario, al menos una vez que tenía esa tabla inicial escrita y almacenada?