Tutorials
Bitwise operators
Altijd al willen weten hoe ze werken? Bekijk dit dan aandachtig!
Pagina 1
Theorie
Inleiding
Zoals iedere programmeur weet, of in ieder geval hoort te weten, bestaat elk karakter uit 1 (één) byte.
Een byte bestaat dan weer uit 8 (acht) bits.
Zo'n bit kan aan of uit staan, of anders gezegt, zo'n bit heeft de 'waarde' 1 of 0.
Daarmee komen we aan op de bitwise operators.
Operatorlijstje
& - AND
| - OR
^ - XOR (exclusive OR)
~ - NOT
>> - shift rechts
<< - shift links
De '&' operator
De bitwise AND wordt vooral gebruikt om bits uit te zetten.
Als in 1 (één) van de 2 bits, een bit de waarde 0 heeft, hebben ze het erna allebei.
Bekijk het volgende voorbeeld:
1001 0101 & 1010 1011 geeft 1000 0001
Zoals je ziet is er precies gebeurt wat daarboven is verteld :)
De '|' operator
De bitwise OR doet precies het tegenovergestelde van de bitwise AND.
Als in 1 (één) van de 2 bits, een bit de waarde 1 heeft, hebben ze het erna allebei.
Voorbeeld:
1001 0101 | 1010 1011 geeft 1011 1111
De '^' operator
De bitwise XOR zet bits aan, op voorwaarde dat de bits die vergeleken worden, niet gelijk zijn.
Als de ene bit waarde 1 heeft, en de ander 0, wordt de uitkomst 1. Bij gelijke waarden wordt dit 0.
Voorbeeld:
1001 0101 ^ 1010 1011 geeft 0011 1110
De '~' operator
De bitwise NOT maakt van elke 0 een 1, en van elke 1 een nul.
Voorbeeld:
~ 1001 0101 geeft 0110 1010
De '<<' & '>>' operators
Met de shift operators verschuif je de bits in een byte naar links of rechts afhankelijk van de operator.
Een shift naar links zal de waarde van de byte met 2 vermenigvuldigen, de rechts zorgt dat er door 2 gedeeld wordt.
Een shift naar links zorgt ervoor dat er rechts een bit met waarde 0 wordt toegevoegd, de rechtse vervalt.
Een shift naar rechts zorgt ervoor dat er links een bit met waarde 0 wordt toegevoegd, de links vervalt.
Let op! Uit de voorgaande twee uitspraken kun je opmaken dat er dus geen rotatie plaatsvind!
De bit die er links of rechts wordt afgeschoven komt niet meer terug!
Voorbeeld:
0000 0001 << 1 (deze 1 (één) staat voor het aantal verschuivingen, dit hoort bij het statement!) geeft 0000 0010
0000 0010 << 2 geeft 0000 1000
1000 0000 >> 1 geeft 0100 0000
0100 0000 >> 4 geeft 0000 0100
Zoals iedere programmeur weet, of in ieder geval hoort te weten, bestaat elk karakter uit 1 (één) byte.
Een byte bestaat dan weer uit 8 (acht) bits.
Zo'n bit kan aan of uit staan, of anders gezegt, zo'n bit heeft de 'waarde' 1 of 0.
Daarmee komen we aan op de bitwise operators.
Operatorlijstje
& - AND
| - OR
^ - XOR (exclusive OR)
~ - NOT
>> - shift rechts
<< - shift links
De '&' operator
De bitwise AND wordt vooral gebruikt om bits uit te zetten.
Als in 1 (één) van de 2 bits, een bit de waarde 0 heeft, hebben ze het erna allebei.
Bekijk het volgende voorbeeld:
1001 0101 & 1010 1011 geeft 1000 0001
Zoals je ziet is er precies gebeurt wat daarboven is verteld :)
De '|' operator
De bitwise OR doet precies het tegenovergestelde van de bitwise AND.
Als in 1 (één) van de 2 bits, een bit de waarde 1 heeft, hebben ze het erna allebei.
Voorbeeld:
1001 0101 | 1010 1011 geeft 1011 1111
De '^' operator
De bitwise XOR zet bits aan, op voorwaarde dat de bits die vergeleken worden, niet gelijk zijn.
Als de ene bit waarde 1 heeft, en de ander 0, wordt de uitkomst 1. Bij gelijke waarden wordt dit 0.
Voorbeeld:
1001 0101 ^ 1010 1011 geeft 0011 1110
De '~' operator
De bitwise NOT maakt van elke 0 een 1, en van elke 1 een nul.
Voorbeeld:
~ 1001 0101 geeft 0110 1010
De '<<' & '>>' operators
Met de shift operators verschuif je de bits in een byte naar links of rechts afhankelijk van de operator.
Een shift naar links zal de waarde van de byte met 2 vermenigvuldigen, de rechts zorgt dat er door 2 gedeeld wordt.
Een shift naar links zorgt ervoor dat er rechts een bit met waarde 0 wordt toegevoegd, de rechtse vervalt.
Een shift naar rechts zorgt ervoor dat er links een bit met waarde 0 wordt toegevoegd, de links vervalt.
Let op! Uit de voorgaande twee uitspraken kun je opmaken dat er dus geen rotatie plaatsvind!
De bit die er links of rechts wordt afgeschoven komt niet meer terug!
Voorbeeld:
0000 0001 << 1 (deze 1 (één) staat voor het aantal verschuivingen, dit hoort bij het statement!) geeft 0000 0010
0000 0010 << 2 geeft 0000 1000
1000 0000 >> 1 geeft 0100 0000
0100 0000 >> 4 geeft 0000 0100
Pagina 2
Toepassen
Inleiding
Nu we de werking van de bitwise operators hebben bekeken, kunnen we er wat mee gaan doen.
We gaan enkele standaar PHP functies herschrijven met de opgedane kennis.
Custom 'strtolower()' en 'strtoupper()'
Deze twee functies maken alle chars geven in de parameter in lower-, danwel uppercase.
Dit gaat wij ook doen, met de volgende voorkennis:
In de ASCII tabel heeft de lower- en uppercase versie van een letter dezelfde bitreeks,
op 1 (één) bit na, de 6e bit (die staat voor 32).
Dat maakt dus elke lowercase letter 32 groter in waarde dan de uppercase variant.
Ok, laten we PHP'en :)
<?php
# Custom strtoupper() door het uitzetten van de 6e bit.
function strhoofdletters( $string )
{
# We willen wel ALLE bytes vervangen, dat doen we dus met 'n loopje.
# Dit kan omdat elke string eigenlijk een array van karakter is.
for( $i = 0; isset( $string[$i] ); $i++ )
{
# Hier gaan we dus de 6e bit uitzetten met de '&' operator.
# We hebben dus een getal nodig met de volgende bitreeks:
# 1101 1111, dit zorgt er dus voor dat de reeks hetzelfde blijft, op de 6e bit na :)
# Dit getal is, 223.
$string[$i] = $string[$i] & 223;
}
# En nu returnen we de uppercase string
return $string;
}
# Custom strtolower door het aanzetten van de 6e bit.
function strkleineletters( $string )
{
# Zelfde als bij strhoofdletters()
for( $i = 0; isset( $string[$i] ); $i++ )
{
# Hier gaan we dus de 6e bit aanzetten met de '|' operator.
# We hebben dus een getal nodig met de volgende bitreeks:
# 0010 0000, dit zorgt er dus voor dat de reeks hetzelfde blijft, op de 6e bit na :)
# En zoals eerder gezegt is dit 32.
$string[$i] = $string[$i] | 32;
}
# En nu returnen we de lowercase string
return $string;
}
?>
Vergelijkingen met de bitwise operators
Hier moet je goed opletten, kijk maar eens naar deze twee voorbeelden:
<?php
$x = 7;
if( $x && 8 ) # Geeft true, $x bestaat en 8 is ook helemaal ok.
if( $x & 8 ) # geeft false, $x is 0000 0111, 8 is 0000 1000 dus de 4e bit is niet geset in $x.
?>
Conclusie
Met de bitwise operators kun je bits in een byte veranderen om deze een andere waarde te geven.
Dit hoef je niet nuttig te vinden maar het is altijd leuk om te weten.
Zo kun je ook je vriendjes imponeren door de volgende functie te gebruiken.
Deze functie laat van een karakter zien uit welke bitreeks deze bestaat.
De kennis die daarbij nodig is, is de volgende:
De 8e bit (de meest linkse) staat voor 128, de 7e voor 64, de 6e voor 32, ..., de 2de voor 2 en de eerste voor 1.
De functie ziet er als volgt uit:
<?php
# Functie die de bitreeks van een karakter laat zien
function display_bits( $char )
{
for( $i = 128; $i > 0; (int) $i = $i / 2 )
{
if( $i & ord( $char ) )
echo '1 ';
else
echo '0 ';
}
}
?>
Succes ermee!
Nu we de werking van de bitwise operators hebben bekeken, kunnen we er wat mee gaan doen.
We gaan enkele standaar PHP functies herschrijven met de opgedane kennis.
Custom 'strtolower()' en 'strtoupper()'
Deze twee functies maken alle chars geven in de parameter in lower-, danwel uppercase.
Dit gaat wij ook doen, met de volgende voorkennis:
In de ASCII tabel heeft de lower- en uppercase versie van een letter dezelfde bitreeks,
op 1 (één) bit na, de 6e bit (die staat voor 32).
Dat maakt dus elke lowercase letter 32 groter in waarde dan de uppercase variant.
Ok, laten we PHP'en :)
<?php
# Custom strtoupper() door het uitzetten van de 6e bit.
function strhoofdletters( $string )
{
# We willen wel ALLE bytes vervangen, dat doen we dus met 'n loopje.
# Dit kan omdat elke string eigenlijk een array van karakter is.
for( $i = 0; isset( $string[$i] ); $i++ )
{
# Hier gaan we dus de 6e bit uitzetten met de '&' operator.
# We hebben dus een getal nodig met de volgende bitreeks:
# 1101 1111, dit zorgt er dus voor dat de reeks hetzelfde blijft, op de 6e bit na :)
# Dit getal is, 223.
$string[$i] = $string[$i] & 223;
}
# En nu returnen we de uppercase string
return $string;
}
# Custom strtolower door het aanzetten van de 6e bit.
function strkleineletters( $string )
{
# Zelfde als bij strhoofdletters()
for( $i = 0; isset( $string[$i] ); $i++ )
{
# Hier gaan we dus de 6e bit aanzetten met de '|' operator.
# We hebben dus een getal nodig met de volgende bitreeks:
# 0010 0000, dit zorgt er dus voor dat de reeks hetzelfde blijft, op de 6e bit na :)
# En zoals eerder gezegt is dit 32.
$string[$i] = $string[$i] | 32;
}
# En nu returnen we de lowercase string
return $string;
}
?>
Vergelijkingen met de bitwise operators
Hier moet je goed opletten, kijk maar eens naar deze twee voorbeelden:
<?php
$x = 7;
if( $x && 8 ) # Geeft true, $x bestaat en 8 is ook helemaal ok.
if( $x & 8 ) # geeft false, $x is 0000 0111, 8 is 0000 1000 dus de 4e bit is niet geset in $x.
?>
Conclusie
Met de bitwise operators kun je bits in een byte veranderen om deze een andere waarde te geven.
Dit hoef je niet nuttig te vinden maar het is altijd leuk om te weten.
Zo kun je ook je vriendjes imponeren door de volgende functie te gebruiken.
Deze functie laat van een karakter zien uit welke bitreeks deze bestaat.
De kennis die daarbij nodig is, is de volgende:
De 8e bit (de meest linkse) staat voor 128, de 7e voor 64, de 6e voor 32, ..., de 2de voor 2 en de eerste voor 1.
De functie ziet er als volgt uit:
<?php
# Functie die de bitreeks van een karakter laat zien
function display_bits( $char )
{
for( $i = 128; $i > 0; (int) $i = $i / 2 )
{
if( $i & ord( $char ) )
echo '1 ';
else
echo '0 ';
}
}
?>
Succes ermee!
Reacties
0