Skip to content

digitalhouse-tech/blog-go-binary-operators

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Introducción

Esta funcionalidad nos permite hacer operaciones pero con numeros binarios, por ejemplo teniendo una variable a con numeros binarios, una variable b, y vamos a realizar operaciones, utilizando Operadores logicos, para que me devuelva un valor x.

A B X
101 100 ?
001 111 ?

Operadores Logicos

Utilizamos operadores lógicos para realizar comparaciones entre 2 valores, se usa para combinar 2 valores y obtener como resultado el valor: 1 (verdadero) o 0 (falso).

Los 3 operadores principales son AND, OR & NOT. Para los siguientes ejemplos vamos a utilizar A y B como variables de entrada y X como variable de salida

AND

Cuando A y B son 1, X es 1, en cualquier otro caso X es 0

OR

Cuando A o B son 1, X es 1, en el unico caso que X puede ser 0 es cuando A y B son 0

NOT

A diferencia de los otros operadores logicos, NOT solo recibe un valor de entrada, el valor de X sera el opuesto de A.

Si A es 1, X sera 0, y si A es 0, X sera 1


Existen otros operadores logicos que vamos a explicar a continuacion:

XOR

Es igual que OR pero con la diferencia que si A y B son 1, X sera 0. El resultado de X es 1 cuando A y B no tienen ambos el mismo valor.

Por ejemplo, si A y B son 1, X sera 0, y si A y B son 0, X sera 0 tambien, en cualquier otro caso X sera 1

NAND

Es el opuesto de AND (AND + NOT), X tendra 0 cuando A y B tengan 1, en cualquier otro caso X tendra 1

NOR

Es el opuesto de OR (OR + NOT), si A y B son 0, X sera 1, en cualquier otro caso X sera 0

XNOR

Es el opuesto de XOR (XOR + NOT), el resultado de X es 1 cuando A y B tienen ambos el mismo valor.


Operadores Binarios en Go

Para los siguientes ejemplos vamos a utilizar una variable a de enteros positivos de 16 bits, le vamos a asignar un valor decimal y vamos a ver en pantalla el valor en formato decimal y en formato binario (utilizamos %b para ver su representacion en numeros binarios)

var a uint16 = 213

fmt.Printf("Number %d in binary is %b\n", a, a)

Left shift & Right shift

Usamos estos operadores para correr n cantidad de veces los numeros binarios, para la derecha (right shift) o para la izquiera (left shift).

Left shift es representado por ‘<<’, por ejemplo:

// numero_binario << cantidad_de_veces_a_mover = resultado

fmt.Printf("Number %d in binary is %b\n", a << 1, a << 1)
// 11010101 << 1  = 110101010 (lo movemos solo 1 vez)

fmt.Printf("Number %d in binary is %b\n", a << 10, a << 10)
// 11010101 << 10 = 101010000000000 (lo movemos 10 veces)

Right shift es representado por ‘>>’, por ejemplo:

// numero_binario > cantidad_de_veces_a_mover = resultado

fmt.Printf("Number %d in binary is %b\n", a >> 1, a >> 1)
// 11010101 >> 1  = 1101010 (lo movemos 1 vez, el numero se va decrementando)

fmt.Printf("Number %d in binary is %b\n", a >> 10, a >> 10)
// 11010101 >> 10  = 0 (lo movemos 10 veces)

fmt.Printf("Number %d in binary is %b\n", a >> 5, a >> 5)
// 11010101 >> 10  = 110 (lo movemos 5 veces)

Va a llegar un punto que no lo vamos a poder decrementar mas y va a ser siempre cero, por ejemplo cuando lo quisimos mover 10 veces.

Operadores logicos

Vamos a declarar otra variable para realizar los ejemplos: (le agrego un formato de 10 a los numeros binarios al mostralo para que me rellene hasta 10 con ceros)

var b uint16 = 20

fmt.Printf("'a': %.3d - %.10b\n", a, a) // a = 0011010101
fmt.Printf("'b': %.3d - %.10b\n\n", b, b) // b = 0000010100

Representacion de los operadores en Go:

  • Si queremos hacer un AND de A y B hacemos: a & b
  • Si queremos hacer un OR de A y B hacemos: a | b
  • Si queremos hacer un XOR de A y B hacemos: a ^ b
  • Si queremos hacer un NOT de A hacemos: ^ a

(el ^ lo usamos tanto para XOR como para NOT)

// AND
fmt.Printf("Bitwise AND: %d - %.10b\n", a & b, a & b)
// 0011010101 AND 0000010100 = 0000010100

// OR
fmt.Printf("Bitwise OR: %d - %.10b\n", a | b, a | b)
// 0011010101 OR 0000010100 = 0011010101

// XOR
fmt.Printf("Bitwise XOR: %d - %.10b\n", a ^ b, a ^ b)
// 0011010101 OR 0000010100 = 0011000001

fmt.Printf("Bitwise NOT: %d - %.10b\n", ^a, ^a)
// NOT 0011010101 = 1111111100101010

En el caso del NOT se ve un numero binario mas grande que los anteriores, esto es porque para los casos anteriores teniamos ceros a la izquierado que no representan nada, pero al hacer un NOT convierte esos ceros en uno que ya representan valores.

Va a rellenar con uno hasta la capacidad que tenga la variable, en este caso son 16 bits.

Para utilizar los operadores NAND, NOR y XNOR, hacemos lo mismo que en el ejemplo anterior pero agregregando un NOT a cada uno.

Por ejemplo, si queremos hacer un NAND lo que hacemos es hacer un NOT de un AND.

// NAND
fmt.Printf("Bitwise NAND: %d - %.10b\n", ^(a & b), ^(a & b))
// NOT (0011010101 AND 0000010100) = 1111111111101011
// 0011010101 NAND 0000010100      = 1111111111101011

// NOR
fmt.Printf("Bitwise NOR: %d - %.10b\n", ^(a | b), ^(a | b))
// NOT (0011010101 OR 0000010100) = 1111111100101010
// 0011010101 NOR 0000010100      = 1111111100101010

// XNOR
fmt.Printf("Bitwise XNOR: %d - %.10b\n", ^(a ^ b), ^(a ^ b))
// NOT (0011010101 XOR 0000010100) = 1111111100111110
// 0011010101 XNOR 0000010100      = 1111111100111110

Ejemplo

Vamos a realizar un pequeño ejemplo utilizando roles, vamos a tener los roles READ, WRITE, UPDATE y DELETE, los cuales cada uno van a estar repesentados por numeros binarios solo teniendo un 1 en diferentes posiciones:

Role Valor
READ 0001
WRITE 0010
UPDATE 0100
DELETE 1000

Vamos a hacerlo de esta manera para poder sumarlos y en base a un numero (la sumatoria de los roles que queramos asignar a un perfil) poder identificar que roles tiene asignado el perfil.

Entonces vamos a definir esas 4 variables que van a representar a los roles:

READ_ROLE := 1         // 0001
WRITE_ROLE := 1 << 1   // 0010
UPDATE_ROLE := 1 << 2  // 0100
DELETE_ROLE := 1 << 3  // 1000

Luego vamos a asignarle roles a un perfil, vamos a agregarle los roles para escribir, leer y borrar:

myProfile := READ_ROLE + WRITE_ROLE + DELETE_ROLE
// Perfil: 1011

Y ahora para validar si el perfil tiene permisos para realizar la operacion vamos a hacer un AND:

  • Si el AND me devuelve el ROLE, entonces tiene permisos
  • Si el AND me devuelve cero, entonces NO tiene permisos
Role Valor role Perfil Resuldato AND
READ 0001 1011 0001
WRITE 0010 1011 0010
UPDATE 0100 1011 0
DELETE 1000 1011 1000
// valido por el role de actualizacion, no tiene permisos
fmt.Println("Does the user have permissions to perform the operation?")
if (0 != (myProfile & UPDATE_ROLE)) {
	fmt.Println("Yes! :D")
}else{
	fmt.Println("No :(")
}
// valido por el role de lectura, tiene permisos
fmt.Println("Does the user have permissions to perform the operation?")
if (0 != (myProfile & READ_ROLE)) {
	fmt.Println("Yes! :D")
}else{
	fmt.Println("No :(")
}

Conclusion

En este artículo, hemos explorado los fundamentos de los operadores binarios en Go y hemos aprendido cómo utilizarlos de manera efectiva en nuestras aplicaciones. Hemos visto cómo estos operadores nos permiten realizar operaciones lógicas y aritméticas a nivel de bits, lo que resulta útil en escenarios específicos. Recuerda que comprender y aplicar correctamente los operadores binarios puede mejorar el rendimiento y la eficiencia de tus programas. ¡Anímate a experimentar con ellos y a explorar más a fondo el poder de los operadores binarios en tus proyectos de Go!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages