Sep 22 2008

Every few months I re-investigate what bitwise is and how it works as I’m always forgetting what it does and how it works, and how useful it actually is. I’ve not yet used bitwise in PHP, so I thought I’d investigate and write a flag system in PHP that uses bit vectors.

First, let me give you an overview of how the flags work underneath. A flag in my example is the number 1, shifted n steps left. I have a list of flags that represent different weather situations, that could happen simultaneously:

define("WEATHER_CLOUDY", (1 << 0));
define("WEATHER_FOGGY", (1 << 1));
define("WEATHER_RAINING", (1 << 2));
define("WEATHER_SNOWING", (1 << 3));

These values, displayed as binary are 1, 2, 4, 8 respectively. The important part however, is not the decimal values, but the binary values, which are 0001, 0010, 0100, 1000 (with leading zeros for ease of understanding).

Lets look more at this, without looking at any more code. What if it was raining AND cloudy? The advantage of using binary is that it can be cloudy and raining. All you do is set the cloudy and raining bits. This would result in a binary value of 0101 (decimal 5). The correlation is simple, the first bit is the SNOWING bit, the second is the RAINING bit, third is FOGGY and the last is CLOUDY. If it’s cloudy, the last bit will be 1, if not 0. And so on… I think you get the picture.

I’ve written (and believe me, it didn’t take long) a couple of functions that allow you to manipulate a value in this way without worrying about the dynamics of it.

function bv_is_set($bits, $bit)
{
	return ($bit == (($bits) & ($bit)));
}
 
function bv_set_bit(&$bits, $bit)
{
	$bits |= $bit;
}
 
function bv_unset_bit(&$bits, $bit)
{
	$bits &= ~$bit;
}
 
function bv_toggle_bit(&$bits, $bit)
{
	$bits ^= $bit;
}

These functions do what they say on the tin. Say you want to store a value that represents a cloudy, rainy day, you would do this:

$weather = 0;
bv_set_bit($weather, WEATHER_CLOUDY);
bv_set_bit($weather, WEATHER_RAINING);

The binary value of $weather is now 0101. You could store this single number in a database or something, the minimum space you would need to store the fact that it is cloudy and raining, is just 4 bits. Thats tiny!!

If you wanted to run a function only when it was snowing, you would use bv_is_set to test this:

bv_toggle_bit($weather, WEATHER_SNOWING);
 
if(bv_is_set($weather, WEATHER_SNOWING))
{
	start_snowplough();
}

The toggle function literally toggles whichever bit. The is_set function tests wether a bit is set or not, the set bit will set a bit, regardless if wether it was set or not previously, and the unset does the opposite. Pretty self-explanatory really.

Leave a Reply