每次用到了再写, 总觉得在干无用的事情, 这次, 写了一个比较通用的, 备份下来..也分享出来....有缺陷/不足请指正...
<?php
/*
+----------------------------------------------------------------------+
| 位域运算库函数 |
+----------------------------------------------------------------------+
| 提供位域运算能力 |
| 此lib提供的函数基于以下前提 |
| 1. 所有偏移量都是从右向左计算 |
| 2. 所有偏移量都从0开始,即0代表最右面的第一位 |
+----------------------------------------------------------------------+
| authors: selfimpr <leiguoguo@yahoo.com.cn> |
| blog: http://blog.youkuaiyun.com/lgg201 |
+----------------------------------------------------------------------+
*/
/**
* 保留$target中从$offset开始的$limit位, 其余位置0
* @param int $target 操作数
* @param int $offset 偏移量
* @param int $limit 保留总位数
* @return int 计算结果
*/
function bit_remain_range(&$target, $offset, $limit) {
return $target &= (pow(2, $limit) - 1) << $offset;
}
/**
* 将$target中从$offset开始的$limit位设置为0, 其余位不变
* @param int $target 操作数
* @param int $offset 偏移量
* @param int $limit 清理总位数
* @return int 计算结果
*/
function bit_clear_range(&$target, $offset, $limit) {
return $target &= ~ ((pow(2, $limit) - 1) << $offset);
}
/**
* 将$target中的第$order位置为0
* @param int $target 操作数
* @param int $order 要操作的位的偏移量
* @return int 计算结果
*/
function bit_clear_single(&$target, $order) {
return bit_clear_range($target, $order, 1);
}
/**
* 将$mask中的$offset起的$limit位合并到$target的对应位置
* @param int $target 操作数
* @param int $mask 要合并的值
* @param int $offset 偏移量
* @param int $limit 合并总位数
* @return int 计算结果
*/
function bit_merge_range(&$target, $mask, $offset, $limit) {
bit_remain_range($mask, $offset, $limit);
bit_clear_range($target, $offset, $limit);
return $target |= $mask;
}
/**
* 将$mask的低$limit位合并到$target的$offset起的$limit位中
* @param int $target 操作数
* @param int $mask 要合并的值
* @param int $offset 偏移量
* @param int $limit 合并总位数
* @return int 计算结果
*/
function bit_set_range(&$target, $mask, $offset, $limit) {
bit_remain_range($mask, 0, $limit);
return bit_merge_range($target, $mask << $offset, $offset, $limit);
}
/**
* 设置$target的$order位为1
* @param int $target 操作数
* @param int $order 要操作的位
* @return int 计算结果
*/
function bit_set_single(&$target, $order) {
return bit_set_range($target, 1, $order, 1);
}
/**
* 计算$target中从$offset起的$limit位值是否等于$value
* @param int $target 操作数
* @param int $value 要比较的值
* @param int $offset 偏移量
* @param int $limit 总位数
* @return bool 比较结果(相等true)
*/
function bit_check_range($target, $value, $offset, $limit) {
bit_remain_range($target, $offset, $limit);
$target >>= $offset;
return $target == $value;
}
/**
* 检查$target的第$order位是否为1
* @param int $target 操作数
* @param int $order 要检查的位
* @return bool 比较结果(是1返回true)
*/
function bit_check_single($target, $order) {
return (bool)bit_remain_range($target, $order, 1);
}
下面是一个简单的单元测试
<?php
/*
+----------------------------------------------------------------------+
| 位域运算库函数单元测试 |
+----------------------------------------------------------------------+
| 提供位域运算能力 |
| 此lib提供的函数基于以下前提 |
| 1. 所有偏移量都是从右向左计算 |
| 2. 所有偏移量都从0开始,即0代表最右面的第一位 |
+----------------------------------------------------------------------+
| authors: selfimpr <leiguoguo@yahoo.com.cn> |
| blog: http://blog.youkuaiyun.com/lgg201 |
+----------------------------------------------------------------------+
*/
require dirname(__FILE__) . '/bit_lib.php';
function test_bit1($method) {
$args = func_get_args();
$func = $args[0];
$target = $args[1];
$args = array_slice($args, 1);
printf("%s:\n%032b\n%032b\n\n", "$func(" . implode(', ', $args) . ")", $target, call_user_func_array($func, $args));
}
function test_bit2($method) {
$args = func_get_args();
$func = $args[0];
$target = $args[1];
$mask = $args[2];
$args = array_slice($args, 1);
printf("%s:\n%032b\n%032b\n%032b\n\n", "$func(" . implode(', ', $args) . ")", $target, $mask, call_user_func_array($func, $args));
}
function test_bit3($method) {
$args = func_get_args();
$func = $args[0];
$target = $args[1];
$args = array_slice($args, 1);
printf("%s:\n%032b\n%s\n\n", "$func(" . implode(', ', $args) . ")", $target, json_encode(call_user_func_array($func, $args)));
}
function test_bit4($method) {
$args = func_get_args();
$func = $args[0];
$target = $args[1];
$mask = $args[2];
$args = array_slice($args, 1);
printf("%s:\n%032b\n%032b\n%s\n\n", "$func(" . implode(', ', $args) . ")", $target, $mask, json_encode(call_user_func_array($func, $args)));
}
#由于bit_lib中函数定义了引用传参, 测试用例为了书写方便没有传递引用, 因此会有警告.
error_reporting(E_ALL & ~E_WARNING);
test_bit1('bit_remain_range', 0xFFFFFFFF, 4, 8);
test_bit1('bit_clear_range', 0xFFFFFFFF, 4, 8);
test_bit1('bit_clear_single', 0xFFFFFFFF, 4);
test_bit2('bit_merge_range', 0xFF00FF00, 0xFFFFF0FF, 4, 8);
test_bit2('bit_set_range', 0xFF00FF00, 0xFFFFF0FF, 4, 16);
test_bit1('bit_set_single', 0xFF00FF00, 4);
test_bit3('bit_check_single', 0xFF00FF00, 8);
test_bit4('bit_check_range', 0xFF00FF00, 0xF0, 4, 8);