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

Nik*_*kov 9 php bit-manipulation array-map

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

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

Pae*_*els 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
Run Code Online (Sandbox Code Playgroud)

  • 当你提供的只是_pseudocode_而没有解决发布的问题时,你怎么能批评Jeff Lambert的真实**PHP**代码呢? (2认同)

Jef*_*ert 1

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

  1. 它是明确的,使用文字而不是数学技巧来完成工作,并且
  2. 适用于您无法假设 2 补码的底层实现,但仍想以这种方式“思考”的情况。(尝试在 PHP 中“存储”位掩码并认为它​​们可以在JavaScript中工作)

请阅读评论并实施@Paebbels 解决方案。性能差异几乎是 7 倍,因此只有在不经常使用的情况下才使用它。

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

$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";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

14是一个1

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));
Run Code Online (Sandbox Code Playgroud)

输出:

数组 ( [0] => 三 1 => 四 [2] => 七 )