Checking Bits With PHP
PHP makes life a lot easier for quick or dirty maintenance scripts, cron jobs or web applications but how does it do for older, not so straight forward problems dealing with bits and bytes? I was surprised how easy it was to manipulate bits in a byte with php. Here is an function that made my life a fair amount easier when having to check for a specific bit in a byte.
This function checks whether a certain bit is set or not given a byte and an index. It returns true if the chosen bit is set. It casts the $value argument to a integer just in case. The index $n goes from left to right so the most significant bit is bit one and the least significant is bit eight. This function will only work for integers between 0 and 255 because that was all I needed at the time. It would be trivial to write either a function to separate bytes in an integer or to increase the amount of bits that this function checks. I originally had a different function here but the Internet quickly told me that there was an easier way to do this.
<?php
function check_bit($value,$n=8)
{
$value = (int)$value;
if($value & (1<<(8-$n))) { return true; }
else { return false; }
}
//Check Bit Usage Example
$test_byte1 = "4";
if( check_bit($test_byte1,2))
echo "Bit 2 is set in ".decbin($test_byte1);
else
echo "Bit 2 is not set in ".decbin($test_byte1);
?>
Here are the php bitwise operator definitions from the php documentation. Look like C much?
$a & $b | And | Bits that are set in both $a and $b are set. |
$a | $b | Or | Bits that are set in either $a or $b are set. |
$a ^ $b | Xor | Bits that are set in $a or $b but not both are set. |
~ $a | Not | Bits that are set in $a are not set, and vice versa. |
$a << $b | Shift left | Shift the bits of $a $b steps to the left (each step means “multiply by two”) |
$a >> $b | Shift right | Shift the bits of $a $b steps to the right (each step means “divide by two”) |
June 16th, 2009 at
1.) It doesn’t make sense for n=1 to represent 128 or 10000000. It makes more sense to represent n=1 in both binary and decimal, along with n=2 = 10, n=3 = 100, etc.
2.) Your function is then accomplished by:
function setbit(int $value, $n)
{
return (($value & (1< 0);
}
See what that does? It moves your bit to the left N-1 times, and’s it with your value, then checks to see if the result is > 0. If the result is > 0, then the bit is set.
http://graphics.stanford.edu/~seander/bithacks.html
June 16th, 2009 at
Nice! I wrote a function to uppercase strings
function uppercase($s) {
$r = “”;
for($i = strlen($s); i > 0; $i–) {
$r .= strtoupper($s[i – 1]);
}
return strrev($r);
}
June 16th, 2009 at
Have a look at the pow() function, which raises a number to a power. This function will replace the above, and work for numbers higher than 255 – but it’s the same basic principle.
function check_bit($value, $n)
{
return $value & pow(2, $n);
}
June 16th, 2009 at
In this case (any many others) it only makes sense to use the least significant bit (the “rightmost”) as starting point for the bit enumeration. Counting starts with 0 (not 1). So the AND-mask computation should read: (1 << $n).
June 16th, 2009 at
If anyone I work with ever wrote a maintenance script or cron job in PHP I would brain them.
June 16th, 2009 at
Why? Whats wrong with PHP for cron or maintenance?
June 16th, 2009 at
@Fritz
For better or for worse, my companys whole infrastructure is duct taped with PHP. It’s ugly as hell, and their systems suck, quite frankly, but it’s the only language i’d be able to write in fast enough to cope with their ever changing demands (I’m still struggling even!)
June 17th, 2009 at
Just off the top of my head, ‘==’ vs ‘===’, a bloated core function library, no portability between versions. The entire language is riddled with obscure gotchas. There are better options for writing maintenance scripts and cron jobs. Leave PHP for writing quick and dirty web applications.