viernes, 5 de noviembre de 2010

Convertir binario

Probando cosas con python, se me ocurrió probar a escribir un programa en el cual introduces 1 byte y te dice su valor. Tras plasmarlo y comprobar que funciona, se me ocurrió escribir una entrada aquí, en el blog, sobre binario. Así que, allá vamos.

Antes de nada, hay que explicar lo necesario sobre el código binario. Los ordenadores son digitales: Solo entienden el lenguaje de dígitos, en este caso binario. (Por lo tanto, 0's y 1's).

Podemos imaginarnos un Bit como un interruptor: Tiene 2 posiciones, encendido o apagado, pues básicamente es eso, el bit puede estar "Encendido" (1) o "Apagado" (0).

Como todo en este mundo, agrupamos los bit's para poder almacenar información: Un conjunto de 8 bit's se denomina Byte. (Por lo tanto, 1 byte = 8 bits). Con un byte, podemos representar 256 significados diferentes (2 elevado a 8) (Rango de 0 a 255). A partir de ahora, para representar "Elevado a" usaré el símbolo ^. Por ejemplo, 2 elevado a 8 lo representaré 2^8. Aunque, esto no es así en la sintaxis de Python (En la cual sería 2**8) Pero, me parece mas cómodo para explicar esta entrada.

Tabla de conversión. Esta imagen no pertenece a DaemonFreedom.
Imaginemos que tenemos el byte 00000101 y queremos saber su valor. Empezando por la derecha, calculamos Bit * 2 ^ 7 para el 1º dígito a la izquierda. Para el segundo dígito a la izquierda, sería Bit * 2 ^6, así hasta llegar el exponente a 0. (Disminuimos 1 por cada Bit).

Por lo tanto, el bit mas a la izquierda (El mas significativo) sería 0*2^7, mientras que el bit menos significativo (El extremo derecha) es 1*2^0.

Todos los resultados son sumados para obtener el valor.

Si realizamos esta cuenta para todos los bit's y sumamos el resultado, obtenemos el valor 5. Si por ejemplo efectuamos la operación con el byte 00001011 obtendría el valor 11.

Os dejo a continuación un código que efectúa esta cuenta (Python):

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def main():
    string =raw_input("Código binario: ")
    ini =0
    num =7
    for element in string:
        aux = int(element)*2**num
        num=num-1
        ini = ini+aux
    print ini
    return 0

if __name__ == '__main__':
    main()

12 comentarios:

  1. Antes que nada, recomendarte inicializar las variables siempre ;) con nulos, si es string = "", si es int = 0, etc.

    Veo un pequeño problema(y no, no os tireis encima mio, se que los numeros binarios en principio son de 8 bits), y es que, claro, este programa es para conseguir el numero correspondiente a la secuencia binaria, pero.. y si yo te doy un numero más alto? o más bajo? daría un error como una catedral, eso se arreglaria de dos formas:
    1)Si solo quieres que sean numero de 8 bits:
    el input se convertiría en algo asi:
    x = 0
    string = ''
    while x !=8 :
    x = 0
    string = input("Código binario: ")
    for i in string:
    x += 1
    y luego ya el codigo para hallar el numero binario, el cual seria recomendable tenerlo en una funcion, por eso de la reutilizacion de codigo y bla,bla,bla...
    he puesto input(), y no raw_input() porque estoy con la version 3.0, si fuese para la 2.x sería raw_input() ;)

    2) Si quieres que sirva para cualquier numero binario, de cualquier extension (dentro de los limites de la memoria, por supuesto):
    Lo unico que debes hacer es en vez de num = 7 (que es el valor por defecto de los binarios de 8 bits) se pondría num = len(string)-1

    Solo eran esas dos objecciones de rendimiento de programa ;)

    ResponderEliminar
  2. Si, pero, el motivo del programa era poner un simple ejemplo, tampoco me puse a indagar como mejorar el algoritmo tal y cual. Pero, se agradece el extra de info ^^

    ResponderEliminar
  3. Ya me imagine que no era algo elaborado, pero los ejemplos que he puesto vienen muy bien, para saber que siempre hay que inicializar (crea un buen habito, y el programa tiende a tener menos errores), y me ha servido a mi para saber que el range(int) solo sirve para los for in jajjajajajaja

    ResponderEliminar
  4. En Python 3, este mismo programa tendrías que hacerlo así:


    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    def main():
    string = input("Código binario: ")
    ini =0
    num =7
    for element in string:
    aux = int(element)*2**num
    num=num-1
    ini = ini+aux
    print(ini)
    return 0

    if __name__ == '__main__':
    main()

    Como ves, solo cambia print() y raw_input pasa a ser input, desapareciendo el primero.

    Un saludo!

    ResponderEliminar
  5. Osea el print en Python 3.x es un método...

    print("Cad")
    print (var)

    Esto ya se va pareciendo a C... jajajja.

    ResponderEliminar
  6. exacto, en python 3.x pasa a ser una función.
    Y lo cierto es que la función es igual que en C.
    Encontrad las diferencias:

    C:
    printf("%s %d", x, y);

    Python 3.x:
    print("%s &d", %(x, y))

    La verdad, pocas diferencias hay jajajajaja

    Lo bueno del input de 3.x es que los numeros los trata como flotantes aunque sea entero, por lo tanto luego en las divisiones te da el resultado correcto. (y mas cosas, pero esta me gusto bastante ^^)

    ResponderEliminar
  7. Método, no función, que esto es todo POO... jaja.

    ResponderEliminar
  8. No tiene porque ser todo POO.
    Puedes hacer POO pero tambien puedes no hacerla. (como se aprende al principio).

    ResponderEliminar
  9. Pero es que en Python todo son objetos, creo recordar... ¿O eso era Ruby? Bueno, al caso, creo que print es un método, a ver si alguien mas opina xD

    ResponderEliminar
  10. > y si yo te doy un numero más alto?
    El número más alto es 2^8 = 256, si das un número más alto, se produce un overflow (siempre hablando de bytes y no de números binarios).

    Ahora, escribiendo estrictamente número binario, la solución sería:
    exponente = 0
    decimal = 0
    for i in nro[::-1]:
    ....decimal += int(i) * 2**exponente
    ....exponente++

    Creo que fue en éste blog que leí el tema del tercer parámetro de los índices (no recuerdo como se llama) en python y sirve para que de vuelta un string.

    >Pero es que en Python todo son objetos, creo recordar... ¿O eso era Ruby?
    En Ruby todo es un objeto, en python tengo mis dudas. print, según creo recordar, en python 3.x es una función, no un método (como si sería en Ruby) o un ¿comando? en python 2.x, y si bien puede ser parecido a lo que es una llamada a printf de C, no tiene por qué ser así:
    print("2 + 2 = ", 2 + 2, end=" ")

    http://docs.python.org/release/3.0.1/whatsnew/3.0.html para más info.

    PD: no iba a contestar, pero como aprendí algo nuevo (dar vuelta un string en python), decidí contestar.
    PD2: los puntos en el código python es porque para el lenguaje la identación es escencial.

    ResponderEliminar
  11. Geniales los comentarios de Anibal como siempre, así da gusto ser corregido. Aunque último los toma como Spam y tengo que seleccionar "No es Spam" para que aparezcan.

    Gracias como siempre (A todos)

    ResponderEliminar