Gli operatori bit a bit entrano in gioco quando si lavora con dati a livello di bit o bit.
Qui elenco una manciata di esempi che utilizzano operazioni bit con esempi di codice (in nessun ordine particolare):
1. Essi sono comuni e parte di molti algoritmi di crittografia e hash funzioni (ad es. MD5).
2. Essi sono spesso utilizzati se si vuole "salvare" lo spazio e si confezione più "bool" variabili in uno int
per esempio, si assegna un po 'per ogni variabile bool. Devi usare operatori bit a bit per essere in grado di cambiare/leggere individualmente i bit.
Per esempio imballaggio 8 bit/Caccio in uno int
:
flags := 0x00 // All flags are 0
flags |= 0x02 // Turn the 2nd bit to 1 (leaving rest unchanged)
flags |= 0xff // Turn 8 bits (0..7) to 1
flags &= 0xfe // Set the lowest bit to 0 (leaving rest unchanged)
istrue := flags&0x04 != 0 // Test if 3rd bit is 1
3. Un'altra area è compressione dei dati in cui si desidera ottenere il massimo da una byte
e utilizzare tutte le bit per archivia/recupera alcune informazioni (un po 'è l'unità di base di informazioni nell'informatica e nelle comunicazioni digitali).
4. Simile alla compressione, ma non proprio la stessa: bitstream. Viene anche utilizzato per risparmiare spazio in un flusso di dati non inviando byte completi ma piuttosto campi con lunghezza di bit arbitraria.
Ho scritto e pubblicato un pacchetto di Reader e Writer a livello di bit altamente ottimizzato, open source qui: github.com/icza/bitio. Vedrai un ampio uso di tutti i tipi di operazioni bit nelle sue fonti.
5. Un altro utilizzo pratico: test determinate proprietà di un (integer) numero. Conoscendo la rappresentazione binaria dei numeri interi (Two's complement) ci sono alcune caratteristiche dei numeri nella loro rappresentazione binaria. Per esempio un numero intero (in complemento a 2) è anche (può essere diviso per 2) se il bit più basso è 0:
func isEven(i int) bool {
return i&0x01 == 0
}
Testando i bit di un numero intero si può anche dire se si tratta di un potere di 2. Ad esempio se un numero positivo contiene solo uno 1
bit, allora è una potenza di 2 (ad esempio2 = 0x02 = 00000010b
, 16 = 0x10 = 00010000
ma, ad esempio, 17 = 0x11 = 00010001
, non alimentazione 2).
6.Molte procedure di codifica/decodifica utilizzano anche operazioni bit. Il più banale è il UTF-8 encoding che utilizza una codifica a lunghezza variabile per rappresentare i punti codice unicode (rune
in Go) come sequenze di byte.
Una semplice variante di una codifica a lunghezza variabile potrebbe essere quella di utilizzare il bit più alto di un byte (8 ° o 7 ° se 0-indexed) per segnalare se sono necessari più byte per decodificare un numero e i 7 bit restanti sono sempre il dati "utili". È possibile verificare il più alto bit e "separato" i 7 bit utili in questo modo:
b := readOneByte()
usefulBits := b & 0x7f
hasMoreBytes := b & 0x80 != 0
L'utile di utilizzare tale codifica a lunghezza variabile è che anche se si utilizza uint64
tipo in Go, che è di 8 byte in memoria , i numeri piccoli possono ancora essere rappresentati utilizzando meno byte (i numeri nell'intervallo 0..127
richiedono solo 1 byte!). Se i campioni che vuoi memorizzare o trasferire hanno molti piccoli valori, questo da solo può comprimere i dati a 1/8 = 12,5%. Il lato negativo è che i grandi numeri (che hanno bit anche nel byte più alto) useranno più di 8 byte. Se vale la pena dipende dall'euristica dei campioni.
X.E l'elenco potrebbe continuare ...
Si può vivere senza conoscere/utilizzare gli operatori bit a bit in Go (e in molti altri linguaggi di programmazione)? La risposta è si. Ma se li conosci, a volte possono renderti la vita più facile e i tuoi programmi più efficienti.
Se vuoi saperne di più sull'argomento, leggi l'articolo di Wikipedia: Bitwise operation e su Google il termine "Tutorial Operatori bitwise", ci sono molti buoni articoli.
Prendi un libro come "Codice" di Petzold per ottenere una conoscenza di base della rappresentazione binaria e dei fondamenti dell'informatica. –