Inicio > C++, Cómo hacer, Independiente > Convertir un número a representación binaria

Convertir un número a representación binaria


Un problema que suele ser recurrente para los estudiantes es el saber cómo convertir un número en su representación binaria. Cabe recordar que un número, por definición, es binario. ¿Qué hace este ejemplo? Pues muestra su representación en unos y ceros, pero en una cadena de texto.

La clase que presento a continuación, binario, es una plantilla que toma cualquier tipo de dato que se desee convertir. La clase presenta un solo miembro privado, _t, de tipo parametrizado, cuyo valor será convertido a una cadena de texto con su representación binaria. A su vez, la clase tiene tres constructores: un constructor por default, un constructor copia y un constructor que inicializa el valor. La clase también tiene un método para obtener el valor y uno para establecerlo, por si no se quiere utilizar el constructor.

Pero lo verdaderamente interesante pasa en el método convertir. Este método hace tres cosas. En primer lugar, toma los bytes del objeto a convertir (i.e. _t) y los guarda en un búfer de memoria. Luego, para cada byte del arreglo, va evaluando cada uno de los bits que lo conforman, y pregunta si el bit es uno o cero, e inserta una representación de texto en una variable, que al final tendrá el valor resuelto. Esto lo podemos ver en el siguiente fragmento:

while (actual != 0)
{
    if (actual & 1) 
        str.insert(0, "1");
    else
        str.insert(0, "0");

    actual >>= 1; 
}

La variable actual guarda el byte actual que se está evaluando. El if hace una conjunción a nivel de bits y pregunta si el bit de hasta la derecha está activo o no. Por ejemplo, suponiendo que actual sea un 3, cuyo binario es 1 1, entonces la operación sería:

    1 1
  & 0 1
 --------
    0 1

Lo cual regresaría una expresión verdadera. Ahora, si en lugar de 3 fuera un 4, tendríamos:

    1 0 0
  & 0 0 1
 ----------
    0 0 0

Lo cuál nos regresaría una expresión falsa. Finalmente, después del if, desplazamos el valor un bit a la derecha. Así, si teníamos un 1 1, desplazando a la derecha tenemos un 0 1; y si tenemos un 1 0 0, entonces ahora tendríamos un 0 1 0. Cuando ya no queden bits, todo se evaluará a cero y se saldrá del bucle.

He aquí el código completo de la clase.

using std::string;
using std::memcpy;

template<class T>
class binario
{
    private:
        T _t;

    public:
        binario()
        {
        }

        binario(const T& t)
        {
            _t = t;
        }

        binario(const binario& convertidor)
        {
            _t = convertidor._t;
        }

        virtual ~binario()
        {
        }

        const T& valor() const
        {
            return _t;
        }

        void valor(const T& t)
        {
            _t = t;
        }

        virtual string convertir() const
        {
            unsigned char* bufer;
            unsigned char actual;
            size_t size;
            string str;

            // convertimos los bytes que tenga el objeto a serializar
            // en un búfer de memoria, copiando byte por byte.
            size = sizeof(T);
            bufer = new unsigned char[size];
            memcpy(bufer, &_t, sizeof(T));

            // cada elemento del búfer es un byte, por lo que tendremos
            // que ir convirtiendo byte por byte. el bucle for siguiente
            // recorre todos los bytes en el búfer.
            for (size_t i = 0; i < size; i++)
            {
                // el byte actual
                actual = bufer[i];

                // un byte tiene, por lo general, ocho bits. lo que
                // hacemos en el siguiente bucle es simular que recorremos
                // bit por bit, para ver si es un uno o un cero. para esto
                // empleamos el operador lógico "y" a nivel de bit, y 
                // preguntamos si el bit de más a la derecha es un uno
                // (en el if). de ser así, lo guardamos en la cadena de
                // texto como "1", y si no, como "0". finalmente, 
                // desplazamos los bits del byte una posición a la
                // derecha, de tal suerte que nos deshacemos del bit
                // ya evaluado y procedemos a evaluar el siguiente bit.
                // cuando ya no queden bits, el byte tendrá un valor
                // de cero y salimos del bucle, para evaluar el 
                // siguiente byte.
                while (actual != 0)
                {
                    if (actual & 1) // ¿el bit de la derecha es un uno?
                        str.insert(0, "1");
                    else
                        str.insert(0, "0");

                    // desplazamos los bits un espacio a la derecha
                    // para deshacernos del bit actualmente evaluado
                    actual >>= 1; 
                }
            }

            delete [] bufer;
            
            return str;
        }
};

El siguiente código es un programita que utiliza dicha clase para obtener la representación binaria de cualquier argumento.


#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include "binario.h"

using std::cout;
using std::cin;
using std::endl;
using std::string;

struct persona
{
    char nombre[20];
    char puesto[20];
    int edad;
    double salario;
};

int main()
{
    binario<int> convEntero;
    binario<char> convCaracter;
    binario<double> convDecimal;
    binario<persona> convPersona;
    string comando;
    int rangoInicial;
    int rangoFinal;
    double decimal;
    Persona persona;

    cout << "***** Un rango de enteros *****" << endl;
    cout << "Escribe el rango inicial: ";
    cin >> rangoInicial;
    cout << "Escribe el rango final: ";
    cin >> rangoFinal;
    cout << endl;
    for (int i = rangoInicial; i <= rangoFinal; i++)
    {
        convEntero.valor(i);
        cout << " El valor para " << convEntero.valor() << " es: " << convEntero.convertir() << endl;
    }
    system("pause");
    cout << endl;

    cout << "***** Una cadena de texto *****" << endl;
    cout << "Escribe una cadena: " << endl;
    cin >> comando;
    for (size_t i = 0; i < comando.size(); i++)
    {
        convCaracter.valor(comando.at(i));
        cout << " " << convCaracter.convertir();
    }
    cout << endl;
    system("pause");
    cout << endl;

    cout << "***** Un valor decimal *****" << endl;
    cout << "Escribe un valor decimal: " << endl;
    cin >> decimal;
    convDecimal.valor(decimal);
    cout << convDecimal.convertir() << endl;
    cout << endl;
    system("pause");
    cout << endl;

    cout << "***** Una estructura plana cualquiera *****" << endl;
    strcpy(persona.nombre, "fernando");
    persona.edad = 27;
    strcpy(persona.puesto, "programador");
    persona.salario = 25751.75;
    convPersona.valor(persona);
    cout << convPersona.convertir() << endl;
    cout << endl;
    system("pause");
    cout << endl;

    return 0;
}


About these ads
Categorías:C++, Cómo hacer, Independiente Etiquetas:
  1. Aún no hay comentarios.
  1. No trackbacks yet.

Deja un comentario

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