Hablando de C: Números Binarios

La ciencia de la computación, trata sobre “datos”, como almacenarlos, interpretarlos y operar con ellos. Cuando trabajamos en C, podemos profundizar a varios niveles.

En C, hay 4 tipos de datos básicos:

  • char: De 1 byte, la palabra char viene de character (8 bits)
  • int:  Por lo general es del tamaño natural  de la maquina, nos sirve para trabajar con enteros (4 bytes)
  • float: Utilizamos los numeros de punto flotante float de precisión sencilla para numeros que requieren parte fraccionaria (4 bytes, precisión hasta 8 digitos)
  • double: Numeros de punto flotante con doble precisión (15 a 17 digitos de precisión)

Si vamos a manejar números muy grandes o muy pequeños, es mejor utilizar double, por su ventaja en precisión sobre float. Además, hay un problema inherente a todas las computadoras …

Para una computadora es difícil representar algunos números con fracciones … es un problema que tienen todas las computadoras por diseño al tratar con números de punto flotante, por lo que si por decir, si lo que queremos es un float con valor a .001, nuestra computadora nos regresa una aproximación, como podemos ver en la imágen:

signos3

Más información sobre los problemas con aritmética de punto flotante: http://docs.python.org.ar/tutorial/2/floatingpoint.html

Teniendo esto en cuenta, un programador debería tener en cuenta considerar aproximaciones y redondeos para evitar este problema. (Si sumas .01 en un ciclo, 10 iteraciones, al final tu computadora no almacena 1, si no una aproximación).

Pero volviendo al tema inicial, para una computadora, el valor de los 0’s y 1’s que tiene almacenados, depende de la interpretación, por si mismos no significan nada.

Ejemplo,

Una variable de tipo char son 8 bits: 00000000

Aunque char significa character, char no es sino un entero pequeño, lo importante es como interpretarlo.

Si de estos 8 bits tomamos el último bit para el signo, entonces solo quedan 7 bits para representar un entero: 00000000

Bajo estos términos, qué valor tendría el número? 10000000

Depende, el número binario 10000000 representa el 128 positivo, pero para representar en binario números negativos usamos el complemento a uno y complemento a dos.

En complemento a uno, negamos los bits del número binario original, esto es, 10000000 se vuelve 01111111. Una curiosidad del complemento a uno es que hay dos formas de representar el cero. En una máquina es más común encontrar que utilice complemento a dos para representar negativos. El complemento a dos solo suma 1 al complemento a uno, esto es:

01111111 + 00000001 = 10000000

Entonces, 128 y -128 se representa igual en binario, pero depende de que consideremos o no el último bit como signo, en la imágen pongo la salida de dos programas en C donde se puede ver mejor esto:

signos4

El código para el primer programa lo pueden descargar de aqui: http://www.mediafire.com/view/z9ewo988uj60ccy/signos.c

En este programa, aunque es sencillo ponemos varios detalles, por decir, en el código estamos aplicamos una máscara a una variable char (la máscara es 0x80) con signo y sin él. También ponemos algunos ejemplos del problema de precisión y el de representación de números fraccionarios.

Creo que es un tema importante por que nos ayuda a entender otras cuestione relevantes, como el casteo de variables.

También nos ayuda a comprender mejor el código ASCII, en el cual se toma el bit de signo para control de transmisión y los caracteres imprimibles solo llegan hasta el 127. https://es.wikipedia.org/wiki/ASCII

Agrego un programa más, para los que quieran experimentar un poco más con los números binarios y sus representaciones, el programa se llama binconv, la siguiente es una captura del mismo corriendo:

signos2

El código lo pueden bajar aquí: http://www.mediafire.com/view/w3ob5ncbswqrgga/binconv.c

Con binconv pueden convertir de binario a decimal, de decimal a binario y con la opción -z imprimir de 0 a N números en su notación decimal, binaria, complemento a uno, a dos, valor hexadecimal y Octal.

Me animé a hacer los programas por que desde hacia tiempo quería investigar un poco más sobre las conversiones decimal a binario y visceversa, comparto el código por que tal vez a alguien más le sirve…

El código de binconv trae varias funciones interesantes y aprovecha el concepto de que un char, es un entero pequeño.

Igual si encuentran algo que no funcione bien agradecería la retroalimentación!

Nota Extra:

Para convertir un entero positivo a una cadena de texto binaria, podemos hacerlo de dos maneras, una es como está en el código de binconv.c (aplicando al entero % 2), pero también lo podemos hacer realizando un corrimiento a la derecha del número y aplicando un AND de bits con máscara 0x1 (o 01 en octal), con lo cual nos regresaría solo el primer bit (contando de derecha a izquierda) … finalmente invertimos la cadena y obtenemos la representación binaria, el código sería algo como lo siguiente:

void dectobin(unsigned n, char *s, int lim)
{
    char *scopy = s;
    
    while (n > 0 && (s - scopy) < lim - 1)
        *s++ = (n & 0x1) + '0', n = n >> 1;

    *s = '\0';
    // Invertimos cadena
    //reverse(scopy);
}

————–

EOF

 

Anuncios

Publicado el febrero 22, 2016 en C y etiquetado en , , , , . Guarda el enlace permanente. Deja un comentario.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: