Algoritmo de Cambio de Base: Teoría, Implementación y Buenas Prácticas en Python
Introducción
Convertir un número de una base a otra es una operación fundamental en informática, criptografía y análisis de datos. Aunque los lenguajes de alto nivel ofrecen funciones integradas, comprender el algoritmo subyacente permite manejar casos especiales como bases no estándar, números extremadamente grandes o requisitos de rendimiento críticos.
Representación Matemática de Bases
Un número n en base b se escribe como:
n = d_k·b^k + d_{k-1}·b^{k-1}+ … + d_0·b^0
donde cada dígito d_i pertenece al rango 0 ≤ d_i < b. El algoritmo de división‑resto (para pasar de decimal a otra base) y el de multiplicación‑acumulación (para ir de otra base a decimal) son los pilares de cualquier conversión.
Algoritmos clásicos de conversión
De decimal a cualquier base (División‑Resto)
- Dividir n entre la base objetivo b.
- Guardar el resto (r) como el dígito menos significativo.
- Reemplazar n por el cociente y repetir hasta que n = 0.
- Los restos recogidos en orden inverso forman la representación en base b.
Este algoritmo es O(log_b n) en complejidad temporal y utiliza O(1) espacio adicional.
De cualquier base a decimal (Multiplicación‑Acumulación)
- Inicializar valor = 0.
- Para cada dígito d_i (de izquierda a derecha):
valor = valor * b + d_i.
Este algoritmo también es O(k), donde k es la longitud del número en la base origen.
Implementación paso a paso en Python
1. Conversión decimal → base b
def dec_to_base(n: int, base: int) -> str:
"""Convierte un entero decimal a una cadena en la base especificada.
Soporta bases entre 2 y 36 (0‑9 + A‑Z)."""
if not (2 <= base <= 36):
raise ValueError('Base debe estar entre 2 y 36')
if n == 0:
return '0'
digits = []
while n > 0:
n, rem = divmod(n, base)
# map 0‑9 → '0'‑'9', 10‑35 → 'A'‑'Z'
digits.append(chr(rem + 55) if rem >= 10 else str(rem))
return ''.join(reversed(digits))
2. Conversión base b → decimal
def base_to_dec(s: str, base: int) -> int:
"""Convierte una cadena en base base a entero decimal.
Acepta tanto minúsculas como mayúsculas para dígitos > 9."""
if not (2 <= base <= 36):
raise ValueError('Base debe estar entre 2 y 36')
s = s.strip().upper()
value = 0
for char in s:
if '0' <= char <= '9':
digit = ord(char) - 48
elif 'A' <= char <= 'Z':
digit = ord(char) - 55
else:
raise ValueError(f'Dígito inválido: {char}')
if digit >= base:
raise ValueError(f'Dígito {char} fuera del rango para base {base}')
value = value * base + digit
return value
Ambas funciones validan la base, gestionan errores de entrada y son compatibles con Python 3.8+.
Comparativa con las funciones nativas de Python
función bin(), oct(), hex()
- Solo admiten bases 2, 8 y 16.
- Devuelven prefijos
0b,0o,0xque a veces deben eliminarse. - Sin validación de entradas no‑numéricas.
función int(string, base)
- Convierte de cualquier base (2‑36) a decimal.
- No tiene equivalente directo para decimal → base arbitraria.
- Puede lanzar
ValueErrorcon mensajes poco claros; nuestra implementación proporciona mensajes más descriptivos.
Optimización y manejo de enteros muy grandes
Python maneja enteros de precisión arbitraria, pero el algoritmo de división‑resto puede volverse costoso para números con millones de bits. Algunas estrategias:
- Chunking: dividir el número en bloques (por ejemplo, 30 bits) y convertir cada bloque por separado usando
pow(base, chunk_size). - Uso de
numpyogmpy2para operaciones de múltiplos‑precisión más rápidas. - Paralelismo: en entornos multi‑core, procesar diferentes bloques en procesos/hilos independientes y combinar resultados.
Ejemplo con gmpy2:
import gmpy2
def dec_to_base_gmp(n: int, base: int) -> str:
if n == 0:
return '0'
digits = []
while n:
n, rem = gmpy2.f_divmod(n, base)
digits.append(chr(int(rem) + 55) if rem >= 10 else str(int(rem)))
return ''.join(reversed(digits))
Seguridad y validación de entrada
En aplicaciones web o API, nunca confíes en la cadena recibida sin validar:
- Limita la longitud máxima (ej. 256 caracteres) para evitar ataques de Denial‑of‑Service.
- Escapa o rechaza caracteres no alfanuméricos.
- Utiliza
try/excepty registra los intentos fallidos para auditoría.
def safe_base_to_dec(s: str, base: int, max_len: int = 256) -> int:
if len(s) > max_len:
raise ValueError('Longitud de cadena excede el límite permitido')
return base_to_dec(s, base)
Resolución de problemas frecuente
| Problema | Causa | Solución |
|---|---|---|
| Resultado vacío o "0" inesperado | Entrada no numérica o base fuera de rango | Validar la base y limpiar la cadena antes de la conversión. |
Excepción ValueError: invalid literal for int() | Carácter fuera del rango permitido | Revisar la tabla de mapeo de dígitos; aceptar minúsculas y mayúsculas. |
| Rendimiento muy bajo con números gigantes | Algoritmo O(log n) sobre Python int puro | Usar gmpy2 o dividir en bloques. |
Mejores prácticas para producción
- Encapsula la lógica en una pequeña librería (
baseconv.py) con pruebas unitarias (pytest). - Documenta la API con
docstringsy genera documentación conSphinx. - Incluye tipado estático (
typing) para facilitar el análisis conmypy. - Configura CI/CD (GitHub Actions, GitLab CI) que ejecute pruebas de rendimiento y cobertura.
Preguntas frecuentes (FAQ)
- ¿Puedo usar bases superiores a 36?
- Python no dispone de símbolos predefinidos más allá de
0‑9yA‑Z. Para bases mayores, define tu propio alfabeto (ej. usando Unicode) y adapta el mapeo de dígitos. - ¿Cómo convierto números fraccionarios?
- Separa la parte entera y la fraccionaria. La entera se convierte con los algoritmos mostrados; la fracción usa multiplicación por la base objetivo y captura la parte entera en cada iteración (similar a la conversión decimal → binario de fracciones).
- ¿Existe una forma más rápida que la división‑resto?
- Para bases que son potencias de 2 (2, 4, 8, 16, 32, 64) puedes usar operaciones de desplazamiento y máscaras de bits, lo que reduce el coste a O(1) por dígito.
Conclusión
Dominar el algoritmo de cambio de base y saber implementarlo de forma segura y eficiente en Python abre la puerta a una gran variedad de casos de uso: generación de identificadores, codificación de datos, análisis de protocolos y mucho más. Con las extensiones mostradas (gmpy2, chunking, validación robusta) podrás escalar la solución desde scripts de una línea hasta servicios de alto rendimiento.
Algoritmo de Cambio de Base: Guía Completa y Ejemplos en Python