首先,我对这个问题的标题写得不好深表歉意。因此,请有英语母语的人适当地更改标题。我的问题很简单,如下所示:
我正在使用integer来存储一个项目的多种类型。例如:
TYPE A = 1
TYPE B = 2
TYPE C = 4
TYPE D = 8
TYPE E = 16
etc...
现在DB中的项具有类型值14,这意味着它已被分配到类型B+C+D。如果它具有类型值,例如9,则意味着它已被分配给type A+D。
我需要一个函数,我将提供单一类型的整数,这个函数将返回整数类型的数组。
我可以迭代所有的整数,并将它们与数字进行比较,但这就是我现在使用的方法,但我正在寻找一些更有效的方法,如果它存在的话?
提前感谢您的帮助。
这里有一个没有任何循环的函数(主要是为了好玩:(:
function getTypes($int)
{
$types = array('Type A','Type B','Type C','Type D','Type E');//defining types
$t = array_reverse(str_split(decbin($int)));//converting $int to an array of bits
$types = array_slice($types,0,ceil(log($int,2)));//slicing the array to the same size as number of bits in the $int
$t = array_combine($types,$t);// Creating a new array where types are keys and bits are values
return array_keys($t,1);// returning an array of keys which have a value of 1
}
然而,这并不意味着它是有效的。如果您使用位掩码,则最好使用位运算符(如位运算符和(&((来检查值。例如,如果你想检查你的整数是否包含类型D和类型E,你应该进行
if ($integer & 8 & 16)
为了检查每个单独的类型,我会给我们一个带有位移算子的循环
function getTypes($int)
{
$result = array();
$types = array('Type A','Type B','Type C','Type D','Type E');
foreach($types as $type)
{
if ($int & 1)//checking if last bit is 1 (exactly the same as if($int%2) )
$result[]=$type;
$int>>=1;//shifting integer's bits to the right (exactly the same as $int = $int / 2)
}
return $result;
}
怎么样?http://codepad.org/AzgdPsL1
解释发生了什么:
- 我创建了一个包含1到
$max_bit
位范围内所有有效类型的$types
数组 - 当数字大于0时进行循环,它将与1进行逐位"与"运算。如果结果为true,这意味着LSB已设置,因此
$type
数组开头的type
适用于此数字。当前类型将添加到返回数组中 -
然后将数字向右移动一位。
<?php function num2type( $num) { $max_bit = 5; $types = array_combine( range( 1, $max_bit), range( ord( 'A'), ord( 'A') + $max_bit - 1)); $return = array(); while( $num > 0) { $current_type = array_shift( $types); if( $num & 0x1) { $return[] = chr( $current_type); } $num = $num >> 1; } return $return; } var_dump( num2type( 8)); // array(1) { [0]=> string(1) "D" } var_dump( num2type( 31)); var_dump( num2type( 14));
输出(针对31(:
array(5) {
[0]=>
string(1) "A"
[1]=>
string(1) "B"
[2]=>
string(1) "C"
[3]=>
string(1) "D"
[4]=>
string(1) "E"
}
14的输出:
array(3) {
[0]=>
string(1) "B"
[1]=>
string(1) "C"
[2]=>
string(1) "D"
}
function check_flag($field, $bit)
{
return (($field | $bit) === $field) ? TRUE : FALSE;
}
$types = array('A' => 1, 'B' => 2, 'C' => 4, 'D' => 8, 'E' => 16);
$db_value = 14;
var_dump(check_flag($db_value, $types['B']));
只需确保将从数据库中获取的值强制转换为integer即可。
编辑:现在我读到你需要设置的所有类型,这里有更多的逻辑:
$set = array();
foreach ($types as $key => $value)
if (check_flag($db_value, $value)) $set[] = $key;
$a = 10;
$scan = 1;
$result = array();
while ($a >= $scan){
if ($a & $scan)
$result[] = $scan;
$scan<<=1; //just a bit shift
}
var_dump($result);