Successivo: Funzioni per i tipi, Precedente: Funzioni di tempo, Su: Funzioni predefinite [Contenuti][Indice]
Io posso spiegarlo per te, ma non posso capirlo per te.
Molti linguaggi consentono di eseguire operazioni bit a bit su due numeri interi. In altre parole, l’operazione è eseguita su ogni successiva coppia di bit presi da ognuno dei due operandi. Tre operazioni comuni sono AND, OR e XOR bit a bit. Queste operazioni sono descritte nella Tabella 9.6.
Operatore booleano | AND | OR | XOR |---+---+---+---+---+--- Operandi | 0 | 1 | 0 | 1 | 0 | 1 ----------+---+---+---+---+---+--- 0 | 0 0 | 0 1 | 0 1 1 | 0 1 | 1 1 | 1 0
Tabella 9.6: Operazioni a livello di bit
Come si vede, il risultato di un’operazione di AND è 1 solo quando entrambi i bit sono 1. Il risultato di un’operazione di OR è 1 se almeno un bit è 1. Il risultato di un’operazione di XOR è 1 se l’uno o l’altro bit è 1, ma non tutti e due. La successiva operazione è il complemento; il complemento di 1 è 0 e il complemento di 0 è 1. Quindi, quest’operazione “inverte” tutti i bit di un dato valore.
Infine, due altre operazioni comuni consistono nello spostare i bit
a sinistra o a destra.
Per esempio, se si ha una stringa di bit ‘10111001’ e la si sposta
a destra di tre bit, si ottiene ‘00010111’.60
Partendo nuovamente da ‘10111001’ e spostandolo a sinistra di tre
bit, si ottiene ‘11001000’. La lista seguente descrive
le funzioni predefinite di gawk
che rendono disponibili
le operazioni a livello di bit.
I parametri facoltativi sono racchiusi tra parentesi quadre ([ ]):
and(
v1,
v2 [,
…])
Restituisce l’AND bit a bit degli argomenti. Gli argomenti devono essere almeno due.
compl(val)
Restituisce il complemento bit a bit di val.
lshift(val, contatore)
Restituisce il valore di val, spostato a sinistra di contatore bit.
or(
v1,
v2 [,
…])
Restituisce l’OR bit a bit degli argomenti. Gli argomenti devono essere almeno due.
rshift(val, contatore)
Restituisce il valore di val, spostato a destra di contatore bit.
xor(
v1,
v2 [,
…])
Restituisce il XOR bit a bit degli argomenti. Gli argomenti devono essere almeno due.
ATTENZIONE: A partire dalla versione di
gawk
versione 4.2, gli operandi negativi non sono consentiti per nessuna di queste funzioni. Un operando negativo produce un errore fatale. Si veda la nota a lato “Attenzione. Non è tutto oro quel che luccica!” per maggiori informazioni sul perché.
Ecco una funzione definita dall’utente (vedi Funzioni definite dall'utente) che illustra l’uso di queste funzioni:
# bits2str --- decodifica un byte in una serie di 0/1 leggibili function bits2str(byte, dati, maschera) { if (byte == 0) return "0" maschera = 1 for (; byte != 0; stringa = rshift(stringa, 1)) dati = (and(byte, maschera) ? "1" : "0") dati while ((length(dati) % 8) != 0) dati = "0" dati return dati }
BEGIN { printf "123 = %s\n", bits2str(123) printf "0123 = %s\n", bits2str(0123) printf "0x99 = %s\n", bits2str(0x99) comp = compl(0x99) printf "compl(0x99) = %#x = %s\n", comp, bits2str(comp) shift = lshift(0x99, 2) printf "lshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift) shift = rshift(0x99, 2) printf "rshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift) }
Questo programma produce il seguente output quando viene eseguito:
$ gawk -f testbits.awk -| 123 = 01111011 -| 0123 = 01010011 -| 0x99 = 10011001 -| compl(0x99) = 0x3fffffffffff66 = 001111111111111111111111111111111 -| 11111111111111101100110 -| lshift(0x99, 2) = 0x264 = 0000001001100100 -| rshift(0x99, 2) = 0x26 = 00100110
La funzione bits2str()
trasforma un numero binario in una stringa.
Inizializzando maschera
a uno otteniamo
un valore binario in cui il bit più a destra è impostato a
uno. Usando questa maschera,
la funzione continua a controllare il bit più a destra.
l’operazione di AND tra la maschera e il valore indica se il
bit più a destra è uno oppure no. Se questo è il caso, un "1"
è concatenato all’inizio della stringa.
Altrimenti, è concatenato uno "0"
.
Il valore è quindi spostato a destra di un bit e il ciclo continua
finché non ci sono più bit.
Se il valore iniziale è zero, viene restituito semplicemente uno "0"
.
Altrimenti, alla fine, al valore ottenuto vengono aggiunti degli zeri a
sinistra, per arrivare a stringhe
di lunghezza multipla di 8, ossia contenenti un numero intero di byte.
Questo è tipico dei computer moderni.
Il codice principale nella regola BEGIN
mostra la differenza tra
i valori decimale e ottale dello stesso numero.
(vedi Numeri non-decimali),
e poi mostra i risultati delle funzioni
compl()
, lshift()
e rshift()
.
Attenzione. Non è tutto oro quel che luccica!
In altri linguaggi, le operazioni "bit a bit" sono eseguite su valori interi, non su valori a virgola mobile. Come regola generale, tali operazioni funzionano meglio se eseguite su interi senza segno.
In una normale operazione, per tutte queste funzioni, prima il valore a virgola
mobile a doppia precisione viene convertito nel tipo intero senza segno di C
più ampio, poi viene eseguita l’operazione "bit a bit". Se il risultato non
può essere rappresentato esattamente come un tipo Comunque, quando si usa il calcolo con precisione arbitraria con l’opzione
-M (vedi Calcolo con precisione arbitraria), il risultato può
essere diverso. Questo è particolarmente evidente con la funzione $ gawk 'BEGIN { print compl(42) }' -| 9007199254740949 $ gawk -M 'BEGIN { print compl(42) }' -| -43 Quel che avviene diventa chiaro quando si stampano i risultati in notazione esadecimale: $ gawk 'BEGIN { printf "%#x\n", compl(42) }' -| 0x1fffffffffffd5 $ gawk -M 'BEGIN { printf "%#x\n", compl(42) }' -| 0xffffffffffffffd5 Quando si usa l’opzione -M, nel dettaglio, In breve, usare |
Questo esempio
presuppone che degli zeri riempiano le posizioni a sinistra.
Per gawk
, è sempre
così, ma in alcuni linguaggi è possibile che le posizioni a sinistra
siano riempite con degli uno.
Per essere più chiari,
la conseguenza è che gawk
può memorizzare solo un determinato
intervallo di valori interi; i numeri al di fuori di questo intervallo vengono
ridotti per rientrare all’interno dell’intervallo.
Successivo: Funzioni per i tipi, Precedente: Funzioni di tempo, Su: Funzioni predefinite [Contenuti][Indice]