Manejar máscaras de binarios

Hola, de nuevo no encuentro forma elegante de resolver un problema, en
principio, sencillo:

Tengo un valor numérico, ejemplo:
num = 192
Ahora quiero saber si en la representación binaria de “num” están
activos los bit 5, 6 y 7 (por separado).

Concretamente 192 = 11000000, así que:

  • bit 5: NO
  • bit 6: SI
  • bit 7: SI

Ahora lo intento hacer con Ruby:

Primero paso el número a binario (no encuentro forma mejor que ésta
guarrada):

num.to_s(2).to_i
=> 11000000

Ahora tendría que hacer un AND binario, pero es que para que el número
sea considerado como binario debe estar en la forma:

0b11000000

¿Cómo consigo ese número en ese formato?

Luego haría el AND binario, para ello necesito el “num” y la máscara
para cada bit en binario.
La máscara la puedo obtener así:
10**5
=> 100000
Pero estamos en las mismas, necesito:
0b100000

Y luego aplicaría:

  • bit 5:
    0b11000000 & 0b100000
    => 0

  • bit 6:
    0b11000000 & 0b1000000
    => 64

  • bit 7:
    0b11000000 & 0b10000000
    => 128

Hay mucha “ñapa” ahí arriba, ¿alguna sugerencia para decorarlo un poco?

Muchas gracias.

El 20/02/08, Iñaki Baz C. [email protected] escribió:

  • bit 6: SI
  • bit 7: SI

También lo podría hacer de otra forma puesto que Ruby permite máscara
binaria netre dos números enteros:

192 & 128
=> 128

Lo intento por esta vía:

  • bit N=6 → 64:

binary = 1
N.downto(1) {binary = binary * 10}
binary
=> 1000000

Pero ahora ¿cómo paso de 1000000 a 64?

Lo podría hacer así:

0b1000000.to_i
=> 64

pero claro, 1000000 lo tengo en la variable “binary”, ¿cómo lo “meto”
ahí dentro? lo siguiente da error:

0b#binary.to_i
SyntaxError: compile error
(irb):139: numeric literal without digits
0b#binary.to_i
^
from (irb):139
from :0

¿Alguna idea? Gracias.

On Feb 20, 2008, at 15:18 , Iñaki Baz C. wrote:

  • bit 7: SI

Ahora lo intento hacer con Ruby:

Primero paso el número a binario (no encuentro forma mejor que ésta
guarrada):

num.to_s(2).to_i
=> 11000000

Ojo, ahi se hace esto:

  • representacion en base 2 de 192
  • eso da una cadena
  • se convierte esa cadena a entero con to_i

El metodo to_i asume que la cadena esta en base 10, de manera que en
realidad has pasado de 192 a 11 millones, has obtenido un numero
distinto.

Si el numero es entero positivo se puede saber directamente si el 7o
bit por la derecha de su representacion en base 2 es 1 de este modo:

1 == num & (1 << 6)

– fxn

2008/2/20 Iñaki Baz C. [email protected]:

No obstante, no llego a entender qué hace ese “1 << 6”, ¿podrías
explicarlo un poco por favor?

Los operadores << y >> son shifts (corrimiento?) de bits a la
izquierda y derecha respectivamente. Un ejemplo:

a = 0001
a << 2
a = 0100

Básicamente lo que estás haciendo es mover todos los bits del número
“n” posiciones a la izquierda o a la derecha. Cuando haces “1 << 6”
estas obteniendo un número
así:
00100000

Que efectivamente es lo que quieres comprobar.

Si mi explicación no es muy clara puedes ir a Google y buscar ejemplos
de “Bit shift operators”

El 20/02/08, Federico B. [email protected] escribió:

Que efectivamente es lo que quieres comprobar.

Si mi explicación no es muy clara puedes ir a Google y buscar ejemplos
de “Bit shift operators”

Entendido perfectamente :wink:

Muchas gracias.

El 20/02/08, Xavier N. [email protected] escribió:

El metodo to_i asume que la cadena esta en base 10, de manera que en
realidad has pasado de 192 a 11 millones, has obtenido un numero
distinto.

Vale, no se me había ocurrido hacer “to_i(2)” para los String.
Entonces puedo hacer:

N = 6 (bit 6)

N.downto(1) {binary = binary * 10}
binary
=> 1000000
binary.to_s.to_i(2)
=> 64

Me sigue pareciendo un poco guarrillo tener que hacer ese “to_s.to_i”
para cambiar la base, ¿no existe algo en plan:
binary.to_base(10)
?

Si el numero es entero positivo se puede saber directamente si el 7o
bit por la derecha de su representacion en base 2 es 1 de este modo:

1 == num & (1 << 6)

Qué buena !!!

65 & (1 << 6)
=> 64

64 & (1 << 6)
=> 64

63 & (1 << 6)
=> 0

128 & (1 << 6)
=> 0

192 & (1 << 6)
=> 64

No obstante, no llego a entender qué hace ese “1 << 6”, ¿podrías
explicarlo un poco por favor?

Muchísimas gracias.

El día 20/02/08, Federico B. [email protected] escribió:

Los operadores << y >> son shifts (corrimiento?)

“Corrimiento” queda feo. Mejor “desplazamiento”

Esta forma la veo correctísima:
192 & 128
=> 128
Porque no usarla?

On Feb 20, 2008, at 16:03 , Xavier N. wrote:

Si el numero es entero positivo se puede saber directamente si el 7o
bit por la derecha de su representacion en base 2 es 1 de este modo:

1 == num & (1 << 6)

He recordado que ademas en Ruby se puede hacer esto

num[6] == 1

Los enteros responden a [], que da acceso directo a sus bits:

2[0] # -> 0
2[1] # -> 1

– fxn