De decimal a binario

6 minutos de lectura

avatar de usuario
cielo oscuro

Tengo un número que me gustaría convertir a binario (de decimal) en C.

Me gustaría que mi binario siempre esté en 5 bits (el decimal nunca pasará de 31). Ya tengo una función que lo hace manualmente dividiendo, pero es difícil aumentarla a 5 bits.

¿Hay alguna manera más fácil? ¿Quizás usando el cambio bit a bit?

También me gustaría que el binario se represente en un char *

Aquí hay una solución elegante:

void getBin(int num, char *str)
{
  *(str+5) = '\0';
  int mask = 0x10 << 1;
  while(mask >>= 1)
    *str++ = !!(mask & num) + '0';
}

Aquí, comenzamos asegurándonos de que la cadena termine en un carácter nulo. Luego, creamos una máscara con una sola en ella (es la máscara que esperaría, desplazada hacia la izquierda una vez para tener en cuenta el cambio en la primera ejecución del condicional while). Cada vez que se recorre el bucle, la máscara se desplaza un lugar a la derecha y, a continuación, el carácter correspondiente se establece en un ‘1’ o un ‘0’ (el !! asegúrese de que estamos agregando un 0 o un 1 a '0'). Finalmente, cuando el 1 en la máscara se desplaza fuera del número, el bucle while termina.

Para probarlo, utilice lo siguiente:

int main()
{
  char str[6];
  getBin(10, str);
  printf("%s\n", str);
  return 0;
}

  • ¿Se romperá esto si la arquitectura usa una representación binaria diferente?

    – señor

    21 de septiembre de 2013 a las 14:55

  • @Kurian Bueno, generará los 5 bits menos significativos en el int. No conozco ninguna arquitectura que tenga una representación inesperada de los números. 0-31 como un int, sin embargo.

    – Aarón Dufour

    21 de septiembre de 2013 a las 18:42

  • @AaronDufour Qué es mask >>= 1 haciendo, es lo mismo que mask = mask >> 1? Esto debe estar en la línea de i=+1

    – Alejandro Cska

    23 de enero de 2016 a las 17:05


  • @AlexanderCska Eso es exactamente lo que es. Como msdn.microsoft.com/en-us/library/474dd6e2.aspx espectáculos, puede agregar = hasta el final de la mayoría de los operadores en C para obtener una versión de asignación.

    – Aarón Dufour

    25 de enero de 2016 a las 1:11

  • @AaronDufour Gracias por la respuesta, me di cuenta de que no entiendo el !!(mask & num) + '0'. ¿Por qué agregas el cero? los !!(mask & num) hace logico andlos !! produce 0 o 1 pero porque el + '0'? No quiero molestarte demasiado, pero traté de usar el código que escribiste y lo encuentro realmente interesante. Soy un programador de Fortran y encuentro C bastante divertido.

    – Alejandro Cska

    25 de enero de 2016 a las 9:57

avatar de usuario
salvatore previti

Si no necesita ceros a la izquierda, puede usar itoa (valor, cadena de salida, base)

Por ejemplo

char s[9];
itoa(10, s, 2);
printf("%s\n", s);

imprimirá

1010

De lo contrario, puede escribir una función muy simple.

void tobin5str(int value, char* output)
{
    int i;
    output[5] = '\0';
    for (i = 4; i >= 0; --i, value >>= 1)
    {
        output[i] = (value & 1) + '0';
    }
}

int main()
{
    char s[6];
    tobin5str(10, s);
    printf("%s\n", s);
    return 0;
}

imprimirá

01010

Un enfoque más genérico puede ser una función que le pregunte cuántos bits convertir.

void tobinstr(int value, int bitsCount, char* output)
{
    int i;
    output[bitsCount] = '\0';
    for (i = bitsCount - 1; i >= 0; --i, value >>= 1)
    {
        output[i] = (value & 1) + '0';
    }
}

Por supuesto, bitsCount debe ser un valor de 1 a 32, y la cadena de búfer debe asignarse al menos a bitsCount + 1 caracteres.

  • itoa () no está definido en el estándar C?

    usuario649198

    1 de diciembre de 2011 a las 5:54

Un enfoque es este:

unsigned int x = 30;

char bits[] = "00000";

bits[4] = (x & 1) + '0';
x >>= 1;
bits[3] = (x & 1) + '0';
x >>= 1;
bits[2] = (x & 1) + '0';
x >>= 1;
bits[1] = (x & 1) + '0';
x >>= 1;
bits[0] = x + '0';

Probablemente no sea el enfoque más elegante…

avatar de usuario
derobert

Para 31 valores, en lugar de hacer malloc para asignar una cadena, seguido de la manipulación de bits para completarla, es posible que desee usar una tabla de búsqueda.

static const char *bitstrings[] = {
    "00000", "00001", "00010", … "11111"
};

Entonces su conversión es tan simple como return bitstrings[i]. Si hace esto con frecuencia, será más rápido (evitando malloc).

De lo contrario, realmente no necesita ningún cambio (excepto para facilitar la escritura de sus constantes); solo puedes usar bit-and:

char *bits = malloc(6);
bits[0] = (i & (1<<4)) ? '1' : '0';   /* you can also just write out the bit values, but the */
bits[1] = (i & (1<<3)) ? '1' : '0';   /* compiler should be able to optimize a constant!     */
⋮
bits[6] = 0; /* null-terminate string*/

Hay una (tal vez) microoptimización que puede hacer si asume ASCII, mediante el uso de la suma. También puedes usar un bucle aquí, pero necesitaba dos líneas para el comentario :-P. En cuanto al rendimiento, ninguno importará. Todo el tiempo se pasa en malloc.

avatar de usuario
Diamantatos Paraskevas

Siempre puede dividirlo y rellenarlo en 5 bits (hice esto para rellenar en 8 bits porque imprimir un carácter como A sería el número 65)

#include <stdio.h>
#include <math.h>
void main(){
int binary[8], number, i; //for 5 bits use binary[5]
do{
printf("input a number: ");
scanf("%d",&number);
fflush(stdin);
}while(number>256 || number <0); //for 5 bits... 31 use number>31 || number <0
for (i=0; i<=7; i++)  // for 5 bits use i<=4
    {
    binary[i]=number%2;
    number = number/2;
    }
for (i=7; i >=0; i--)  //for 5 bits use i=4
    printf("%d", binary[i]);
number=0; // its allready 0.
for (i=0; i<=7; i++)  //for 5 bits use i<=4
    {
    number=number+binary[i]*pow(2,i);
    }
printf("\n%c",number);
}

avatar de usuario
Dmitri

Ya que solo está trabajando con 5 bits, ¿por qué no usar una tabla de búsqueda? Algo como lo siguiente:

/* Convert nstr to a number (decimal) and put a string representation of the
 * lowest 5 bits in dest (which must be at least 6 chars long) */
void getBinStr(char *dest, const char *nstr)
{
  char *lkup[32] = { 
    "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111",
    "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111",
    "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111",
    "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111" };
  strcpy(dest, lkup[atoi(nstr) & 0x1f]);
}

O un interruptor:

void getBinStr(char *dest, const char *nstr)
{
  switch (atoi(nstr)) {
    case 31:  strcpy(dest,"11111"); break;
    case 30:  strcpy(dest,"11110"); break;
    ...
    case 1:   strcpy(dest,"00001"); break;
    case 0:   strcpy(dest,"00000"); break;
    default:  strcpy(dest,"error");
  }
}

O si eso parece demasiado largo, tal vez algo como lo siguiente:

void getBinStr(char *dest, const char *nstr)
{
  unsigned x = atoi(nstr);
  dest[0] = (x & 0x10) ? '1' : '0';
  dest[1] = (x & 0x08) ? '1' : '0';
  dest[2] = (x & 0x04) ? '1' : '0';
  dest[3] = (x & 0x02) ? '1' : '0';
  dest[4] = (x & 0x01) ? '1' : '0';
  dest[5] = '\0';
}

Normalmente preferiría uno de los dos primeros, pero el último podría ser mejor si por alguna razón los otros son demasiado grandes (como el código para un microcontrolador pequeño).

Todos estos asumen que desea que el resultado se deje relleno con ceros a 5 bits.

avatar de usuario
Pramod

#include <stdio.h>
#include <string.h>

char numstr[9024];
int i = 0;

void format(int n, int base);
void printreverse(char *s);

int main()
{
     int testnum = 312;    // some random test number
     format(testnum, 2);   // 2 for binary
     printreverse(numstr);
     putchar('\n');

     return 0;
}

void format(int n, int base)
{
    if (n > 0) {
        char tmp = (n % base) + '0';
        numstr[i++] = tmp;

        // If we put this above other two we don't need printreverse,
        // But then we will have unwanted results in other places of numstr if we can't reset it

        format(n/base, base); 
    } else
        numstr[i] = '\0'; // terminating character
}

void printreverse(char *s)
{
    long len = strlen(s);
    while (len-->0)
        putchar(s[len]);
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad