Revista Tecnología

Cómo extraer la parte alta y la parte baja de un número con varios ejemplos en C

Publicado el 30 diciembre 2015 por Gaspar Fernández Moreno @gaspar_fm

Cómo extraer parte alta baja número varios ejemplosCómo extraer la parte alta y la parte baja de un número con varios ejemplos en C

En ocasiones, en C, sobre todo, una misma variable numérica (un entero, un short, o incluso un char) encierra en sus bits más valores que nos pueden resultar interesantes por separado. Sobre todo, por optimizar la memoria, en lugar de reservar dos variables de tipo entero de 32bits para almacenar valores pequeños, queramos empaquetar en el mismo valor entero los dos valores y luego extraerlos cuando los necesitemos. Esto lo podemos ver en sistemas empotrados en los que estamos muy limitados en memoria.

De la misma forma, si estamos trabajando con grandes bases de datos, con miles de registros (o millones), podremos ahorrar varios megabytes de espacio si reunimos varios valores pequeños en un mismo valor más grande.

En este caso, nos vamos a centrar en una variable de tipo unsigned short (normalmente, 16bits), aunque podremos verificar el tamaño en nuestro sistema con sizeof(). Dicha variable de tipo short, queremos descomponerla en dos variables de tipo char a las que llamaremos parte alta a la parte más significativa de la palabra (es decir, a la que más peso tiene), y parte baja a la que menos peso tiene.

Por ejemplo, el número 43679 podemos representarlo en binario como 10101010 10011111, la parte alta sería 10101010 y la baja 10011111. ¿ Cómo podemos extraer dichos valores en C ?

Nota, hecho en Little Endian

Algunos de estos ejemplos dependerán del sistema que use nuestra plataforma para representar los números de más de un byte. Estos ejemplos están probados en un sistema little endian, con un procesador Intel, puede que si usas otro tipo de CPU, los resultados no sean los mismos, ya que los números grandes de más de un byte, se almacenarán de forma diferente.

Como destino, variables unsigned char

Como el tamaño de cada una de las partes es 8bits, vamos a almacenar los valores resultantes en un unsigned char, de esta forma, nos quitaremos muchos problemas, ya que la parte baja la podemos sacar directamente, y en este caso, la parte alta la calcularemos desplazando los bits del número original a la derecha (operador >>):

Como destino, variables tipo unsigned char

Pero claro, esto de hacer partebaja = numero, no nos valdrá si el tamaño de la variable resultante es mayor al número de bits que tenemos. Ahora mismo, al tener la variable resultante partebaja el número de bits exactos que queremos extraer se van a copiar tal cual desde número y como partebaja es más pequeña que número sólo se copiará una parte.

En otro caso, si en la variable caben más bits de los necesarios, necesitamos transformar el número, dos operaciones que me vienen a la cabeza son:

  • Desplazar número primero a la derecha y luego a la izquierda: al desplazar número a la derecha, la parte alta se perderá, y al desplazar a la izquierda de nuevo, en la parte alta habrá ceros. Con este método tenemos que tener muy en cuenta los tamaños. Por ejemplo:
  • Utilizar una máscara para extraer el número, en este caso la máscara sería 00000000 11111111, es decir, 255 en decimal. Con esto queremos que sólo se copien los valores que están a uno, por lo que ignoraríamos la parte alta y sólo nos quedaríamos con la baja:

    Al igual que 255 podemos escribir 0xFF, es decir, su valor hexadecimal. Pero claro, si eso lo consideráis un poco feo al escribir un número a pelo, aunque sea un valor como este, siempre podéis decirle a C que lo calcule. Es decir, lléname un short de unos y luego desplázalo a la derecha, con lo que nos quedaría la máscara deseada:

    O incluso podemos llenar directamente un unsigned char de unos y listo, no tenemos que desplazar nada:

Un inciso para ver los valores en binario

Está muy bien ver los valores con números enteros, pero podemos ayudarnos de un pequeño código que publiqué hace unos días para visualizar el valor en base2 de un número. El tema quedaría así:

Usando punteros

Puede que este método sea más fácil si tenemos manejo con punteros. En este caso, tendremos lo siguiente:

aquí podríamos controlar el caso en el que compilemos en un big-endian cambiando el nombre de las variables *partealta y *partebaja.

Dejo también el ejemplo para copiar y pegar, y ver los valores en binario:

¿ Dudas ? ¿ Comentarios ? Dejadlos aquí abajo.

Foto: Jay Wennington ( Unsplash)


Volver a la Portada de Logo Paperblog