Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


9.4  Manejo de bits


  Obtener el patrón de bits de un número entero sin signo:  se acepta una entrada numérica por el teclado hasta que se pulsa Intro (0x0D). El programa proporciona la imagen del patrón de bits correspondiente al número introducido.

#include <iostream.h>

int main() {        // ==========

  unsigned long m, res;
  int iter =0;

  std::cout << "Introduzca un numero positivo (Intro para terminar):" << std::endl;
  cin >> m;
  if (m < 0) std::cout << "Numero NO valido." << endl;
  else if (m <= 255)   iter = 8;
  else if (m <= 65535) iter = 16;
  else if (m <= 4294967295) iter = 32;
  for (int i = iter; i > 0; i--) {
    res = m & static_cast <unsigned long> (pow(2, i-1));
    cout << (res == 0? "-0": "-1");

  }
  cout << endl;
  return 0;
}

Resultados obtenidos con diversos valores:

m = 128       ->  -1-0-0-0-0-0-0-0

m = 3250     ->  -0-0-0-0-1-1-0-0-1-0-1-1-0-0-1-0

m = 112448  ->  -0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-1-1-0-1-1-0-1-1-1-0-1-0-0-0-0-0-0


   A continuación se incluye una versión perfeccionada del anterior.  El programa acepta igualmente un entero sin signo; a continuación puede seleccionarse la longitud del patrón de bits correspondiente:  "C" para carácter (8 bits);  "S" para unsigned short (16 bits) y "L" para unsigned log (32 bits). 

#include <iostream>
#include <conio.h>
using namespace std;

void mapC(unsigned char);    // Prototipos de las funciones que
void mapS(unsigned short);   // mostrarán el patrón de bits del
void mapL(unsigned long);    // número introducido

int main() {                 // ====================
   int val;                  // variables auxiliares
   bool ok = false;
   double uDouble = 0;
   while (true) {            // bucle principal
      cout << "\r\nIntroduzca un numero (Intro para terminar):" << endl;

      cin >> uDouble;
      cout << "\r\nValor seleccionado: " << uDouble << endl;
      ok = false;
      while ( true ) {
         cout << "\r\nSeleccione longitud: C=8 bits, S=16 bits, L=32 bits (ESC = salir)";
         val = getch();
         if (val == '\x1B') break;    // Escape
         else if (val==67 || val==99 || val==83 || val==115 || val==76 || val==108) {
            ok = true;
            break;
         } else {
            cout << "\r\nEl caracter NO es valido" << endl;
         }
      }
      if (! ok) break; // terminar ejecucion
      if (uDouble < 0 ) {
         cout << "\r\nEl numero NO es correcto (solo valores positivos)" << endl;
         continue;
      }
      switch (val) {
         case 67: case 99:        // unsigned char (8 bits)
            if (uDouble > UCHAR_MAX) {
               cout << "\r\nValor demasiado grande para 8 bits" << endl;
               break;
            }
            mapC((unsigned char) uDouble);    // observe el "casting"
            break;
         case 83: case 115: // unsigned short (16 bits)
            if (uDouble > USHRT_MAX) {
               cout << "\r\nValor demasiado grande para 16 bits" << endl;
               break;
            }
            mapS((unsigned short) uDouble);
            break;
         case 76: case 108: // unsigned long (32 bits)
            if (uDouble > ULONG_MAX) {
               cout << "\r\nValor demasiado grande para 16 bits" << endl;
               break;
            }
            mapL((unsigned long) uDouble);
            break;
      }
   }
   return EXIT_SUCCESS;
}

void mapC (unsigned char value) {     // patrón de 8 bits
   cout << "\r\n\nMapa de bits = ";
   for(int i = 7; i >= 0; i--) cout << ((value & (1 << i)) ? "1" : "0");
   cout << "\r\n";
}

void mapS (unsigned short value) {    // patrón de 16 bits
   cout << "\r\n\nMapa de bits = ";
   for(int i = 15; i >= 8; i--) cout << ((value & (1 << i)) ? "1" : "0");
   cout << " ";
   for(int j = 7; j >= 0; j--) cout << ((value & (1 << j)) ? "1" : "0");
   cout << "\r\n";
}

void mapL (unsigned long value) {     // patrón de 32 bits
   cout << "\r\n\nMapa de bits = ";
   for(int i = 31; i >= 24; i--) cout << ((value & (1 << i)) ? "1" : "0");
   cout << " ";
   for(int j = 23; j >= 16; j--) cout << ((value & (1 << j)) ? "1" : "0");
   cout << "-";
   for(int k = 15; k >= 8; k--) cout << ((value & (1 << k)) ? "1" : "0");
   cout << " ";
   for(int l = 7; l >= 0; l--) cout << ((value & (1 << l)) ? "1" : "0");
   cout << "\r\n";
}

Resultados para diversos valores de entrada:

128 y "C" -->  Mapa de bits = 10000000

128 y "S" -->  Mapa de bits = 00000000 10000000

255 y "S" --> Mapa de bits = 00000000 11111111

256 y "S" --> Mapa de bits = 00000001 00000000

4,294,967,040 y "L" -->  Mapa de bits = 11111111 11111111-11111111 00000000

Comentario:

Se ha dispuesto un control para verificar que la cantidad numérica está dentro del rango permitido a la longitud del patrón escogido. Este control se realiza mediante las constantes manifiestas UCHAR_MAX, USHRT_MAX y ULONG_MAX ( 2.2.4).

La cantidad introducida se asocia inicialmente a un número suficientemente grande (un double de 64 bitrs) para albergar cualquier entero.  Posteriormente se realiza un casting adecuado a la longitud elegida; a continuación se invoca la función que muestra el patrón de bits según la longitud seleccionada.  Observe que se supone una distribución "Big-endian" ( 2.2.6a), el octeto más significativo se muestra a la izquierda.

El programa puede ser útil para comprobar el resultado de los "experimentos" y ejercicios relativos a los operadores de manejo de bits ( 4.9.3).