在PHP中获取基于位掩码的数组值

时间:2014-12-17 22:00:29

标签: php bit-manipulation array-map

我有一个用于位掩码的32位整数和一个包含32个值的数组。如何只从数组中获取哪些索引对应于位掩码中非零位的位置?

例如,假设位掩码为49152,二进制为1100000000000000。因此,我必须从数组中获取索引为14和15的元素的值。

3 个答案:

答案 0 :(得分:6)

你需要在掩码上循环32步并测试它为'1',如果设置了这个位,你可以将元素复制到你得到的数组。

伪代码:

m = 0x00000001
j = 0
for i in 0 to 31 loop
  if ((mask & m) = m) then   // bit is set in mask
    result(j++) := input(i)
  end if
  m := m << 1     // shift left by 1 or multiply by 2
end loop

答案 1 :(得分:1)

这里有一些PHP代码,但请注意它效率很低。我使用这个算法是因为:

  1. 这是明确的,并使用文字而不是数学技巧来完成工作,
  2. 在您无法承担2s补充的基础实施的情况下工作,但仍然想要思考&#39;那样。 (尝试在PHP中存储&#39;位掩码并认为它​​们可以在JavaScript中工作)
  3. 请阅读评论并实施@Paebbels解决方案。性能差异几乎是7倍,所以如果不经常使用它,实际上只能使用它。

    利用base_convert将基数为10的整数转换为基数2,将字符串拆分为字符数组,反转数组,然后迭代查找1s。

    $mask = 49152; // 0xC000
    
    // Find which positions in the mask contain a '1'
    $bitArray = array_reverse(str_split(base_convert($mask, 10, 2)));
    
    foreach($bitArray as $k => $v) {
        if($v) {
            echo $k . " is a one\n";
        }
    }
    

    输出:

      

    14是一个

         

    15是一个

    作为一项功能:

    function extractElements($mask, array $input) 
    {
        $output = array();
        $bitArray = array_reverse(str_split(base_convert($mask, 10, 2)));
    
        foreach($bitArray as $k => $v) {
            if($v && isset($input[$k])) {
                $output[] = $input[$k];
            }
        }
    
        return $output;
    }
    
    $mask = 76; // 0x4C
    $input = [
        'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'
    ];
    
    print_r(extractElements($mask, $input));
    

    输出:

      

    阵   (      [0] =&gt;三      1 =&gt;四      [2] =&gt;七   )

答案 2 :(得分:0)

我已经实现了满足您需求的功能,此外:

  • 可以处理较小或较大的数据类型

  • 不仅保存索引,还保存值


function extractMask($mask, &$idxs, &$values) {
    for($i = 0, $valueToCompare = 1; $valueToCompare <= $mask; $i++, $valueToCompare <<= 1) {
        if ($mask & $valueToCompare){ 
            $idxs[] = $i;
            $values[] = $valueToCompare;
        }
    }
}

// usage:
extractMask(49152, $idxs, $values);

// results:
var_dump($idxs);
var_dump($values);

为了给人留下深刻的印象,这是一个JS代码段:

function extractMask(mask) {
  var result = {idxs: [], values: []};
  for(i = 0, valueToCompare = 1; valueToCompare <= mask; i++, valueToCompare <<= 1) {
    if (mask & valueToCompare){ 
      result.idxs.push(i);
      result.values.push(valueToCompare);
    }
  }
  return result;
}

//====================== UI ==========================
var anchor = document.getElementsByTagName("a")[0];
var input = document.getElementsByTagName("input")[0];
anchor.addEventListener("click", function(e) {
  var result = extractMask(input.value);
  console.log(result);
});
input.addEventListener("keyup", function (e) {
  if (e.keyCode == 13) {
    var result = extractMask(input.value);
    console.log(result);
  }
});
//====================================================
<input value="49152" />
<a href="#">calculate</a>