Publi

Cambio de base (de base b1 a b2… hasta base36 o tal vez más)

Hace tiempo tuve la necesidad de hacer una función de cambios de base, pero que no estuviera limitada, es decir, no tuviera definido qué base vamos a introducir y qué base debe devolver. Es decir, convertiremos un número en base b1 a base b2; la limitación, el número de caracteres con los que contemos, en el ejemplo hay hasta base 36, y es fácil extenderlo hasta base256… un número en hexadecimal no tiene desde el 0 al 9 y de la A a la F, pues un base36, del 0 al 9 y de la A a la Z. Con un poco de imaginación podremos sacar muchas ideas de este fragmento. Incluye programa de ejemplo:

Hace tiempo tuve la necesidad de hacer una función de cambios de base, pero que no estuviera limitada, es decir, no tuviera definido qué base vamos a introducir y qué base debe devolver. Es decir, convertiremos un número en base b1 a base b2; la limitación, el número de caracteres con los que contemos, en el ejemplo hay hasta base 36, y es fácil extenderlo hasta base64, base256, por ejemplo… con un poco de imaginación podremos sacar muchas ideas de este fragmento. Incluye programa de ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <stdio.h>
#include <string.h>
#include "strutils.h"

void cambiobase (char *n1, int b1, char *n2, int b2)
{
  int lnum = strlen(n1);        /* Longitud de nuestro número */
  /* Caracteres que forman todos los posibles números hasta base 36 */
  char numeros[37]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  int divide;
  int i;
  int posn=0;
  int long2;

  do
    {
      divide = 0;
      long2 = 0;                /* Será un puntero de n1, */
                                /* ya que iremos modificando su valor, long2 */
                                /* nos indicará por dónde vamos */

      for (i=0; i<lnum; i++)
        {
          /* divide vale lo que valía antes multiplicado por la base + el número que acabamos de extraer */
          /* que coincidirá con la posición del carácter dentro del array de numeros[] */
          divide=divide*b1+strchr(numeros, n1[i])-(char*)&numeros;

          if (divide>=b2)
            {
              /* Si el número resultante es mayor o igual a la base */
              n1[long2] = numeros [(int) divide / b2]; /* Modificaremos el dígito long2 de n1, */
                                /*  y este será el número divide/b2 en base b1  */
              divide = divide % b2; /* divide será el resto de la división */
              long2++;
            }
          else if (long2>0)
            {
              n1[long2] = '0';  /* divide<b2, pero en iteraciones anteriores ha sido >= */
              long2++;
            }
        }

      lnum=long2;
      /* hemos hallado un dígito de n2. Su valor será divide */
      n2[posn] = numeros[divide];
      posn++;                   /* posn es el puntero del nuevo número */
    } while (long2!=0);

  n2[posn] = '\0';
  n2=strrev(n2, posn);
}

int main()
{
  char num1[20], num2[20];
  int base1, base2;
  printf("Numero a convertir:");
  scanf("%s", num1);
  printf("¿En qué base está ese número? ");
  scanf("%d", &base1);
  printf("¿A qué base quieres convertirlo? ");
  scanf("%d", &base2);

  cambiobase(num1, base1, num2, base2);

  printf("\n%s\n", num2);

  return 0;
}

La idea principal la saqué hace tiempo de un código escrito en otro lenguaje.
Tenemos que tener en cuenta que esta función utiliza a strutils.h (ver anterior post), aunque también podéis copiar directamente la función strrev y a compilar!!
Todo esto es debido a que el algoritmo para cambiar la base genera el número (como una cadena, pero al fin y al cabo un número) al revés, es decir el dígito de menor peso primero.

También podría interesarte...

Leave a Reply