Medio · sistemas numéricos

Conversión de base

Ya sabes convertir a binario. Lo único que cambia para otras bases es la base, y que a partir de 10 se acaban los caracteres de dígito.

En una fraseToma n % base como siguiente dígito y divide n entre base, y luego imprime los dígitos al revés: los dígitos mayores que 9 pasan a A–F, y 0 se imprime como 0.

El problema

Entrada: Una línea con dos enteros: n (0 ≤ n ≤ 1,000,000) y base (2 ≤ base ≤ 16).

Salida: n escrito en esa base. Los dígitos mayores que 9 son letras mayúsculas A–F. Si n es 0, imprime 0.

Ejemplos:

EntradaSalida
255 16FF
10 21010
0 20

Los restos salen al revés. 10 en base 2 produce los restos 0, 1, 0, 1, que es la respuesta leída al revés. Recógelos y luego imprímelos en orden inverso.

Tu solución

main.cpp — tu solución
Entrada personalizada para «Ejecutar mi entrada»

La corrección corre en tu navegador contra pruebas ocultas. Un bucle infinito se corta a los 3 segundos — aun así, asegúrate de que todo bucle tenga salida. Tu código se guarda solo mientras escribes.

¿Atascado? Pistas

Pista 1 — Parte del binario que ya escribiste

En el problema del binario hacías n % 2 y n / 2. Cambia el 2 por base y el algoritmo no cambia: nunca le importó cuál era la base. Ese es el sentido de una solución general.

Pista 2 — Los dígitos mayores que 9 necesitan conversión

El resto es un número 0–15, pero debes guardar un carácter. Para 0–9 es '0' + r; para 10–15, 'A' + (r - 10). Un ternario hace ambos: r < 10 ? '0' + r : 'A' + r - 10.

Pista 3 — El cero es el caso que rompe el bucle

while (n > 0) no se ejecuta ni una vez cuando n es 0, así que no se recoge nada y se imprime una línea vacía. Resuélvelo antes del bucle: si n == 0, imprime 0 y termina. Es el mismo caso límite que hace tropezar a toda rutina de "convertir un número en dígitos".

Solución (¡inténtalo primero!)
#include <iostream>
using namespace std;

int main() {
    int n, base;
    cin >> n >> base;

    if (n == 0) {
        cout << 0 << endl;
        return 0;
    }

    char digit[64];
    int k = 0;
    while (n > 0) {
        int r = n % base;
        digit[k] = (r < 10) ? ('0' + r) : ('A' + r - 10);
        k++;
        n = n / base;
    }

    for (int i = k - 1; i >= 0; i--) cout << digit[i];
    cout << endl;
    return 0;
}

Los restos de la división repetida, leídos al revés, son los dígitos. Esa sola frase explica a la vez el binario, el octal, el hexadecimal y cualquier sistema posicional: solo cambia la rapidez con que el número se encoge. La dirección inversa (de una cadena en cierta base a un entero) es el mismo bucle al revés, n = n * base + digit, que es literalmente lo que hacen stoi y cin >> por dentro. Ahora, una ordenación en la que nunca comparas nada: Ordenación por conteo.

Análisis profundo

Por qué funciona

Los restos de la división repetida, leídos al revés, son los dígitos. Esa frase explica a la vez todos los sistemas posicionales.

El coste

O(log_base n) divisiones. A mayor base, menos pasos: mil millones son 30 divisiones en binario pero solo 8 en hexadecimal.

Dónde falla

  • Olvidar invertir: los restos salen al revés. 10 en binario da 0,1,0,1; impreso en orden eso es 0101.
  • Faltar el caso n == 0: while (n > 0) no se ejecuta y se imprime una línea vacía. El cero es 0 en cualquier base.

Siguiente paso

Una ordenación que no compara nada: Ordenación por conteo.

Dos cosas para recordar

  • Lee los restos al revés: binario, octal y hex son esa misma frase.
  • Trata el 0 aparte, o imprimirás una línea vacía.
🐞 Esta versión falla: ábrela y pruébala

Restos impresos en el orden en que salieron: los dígitos quedan al revés

#include <iostream>
using namespace std;

int main() {
    int n, base;
    cin >> n >> base;

    if (n == 0) {
        cout << 0 << endl;
        return 0;
    }

    char digit[64];
    int k = 0;
    while (n > 0) {
        int r = n % base;
        digit[k] = (r < 10) ? ('0' + r) : ('A' + r - 10);
        k++;
        n = n / base;
    }

    for (int i = 0; i < k; i++) cout << digit[i];
    cout << endl;
    return 0;
}