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

在PHP中基于位掩码获取数组值,php,bit-manipulation,array-map,Php,Bit Manipulation,Array Map,我有一个用于位掩码的32位整数和一个具有32个值的数组。如何仅从数组中获取那些索引对应于位掩码中非零位位置的值 例如,假设位掩码为49152,二进制为1100000000000000。因此,我必须从数组中获取索引为14和15的元素的值。您需要在掩码上分32步循环,并测试其“1”,如果设置了此位,您可以将元素复制到生成的数组中 伪代码: m = 0x00000001 j = 0 for i in 0 to 31 loop if ((mask & m) = m) then // bi

我有一个用于位掩码的32位整数和一个具有32个值的数组。如何仅从数组中获取那些索引对应于位掩码中非零位位置的值


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

您需要在掩码上分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
m=0x00000001
j=0
对于0到31循环中的i
如果((掩码&m)=m),则在掩码中设置//位
结果(j++):=输入(i)
如果结束

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

  • 它是明确的,使用文字而不是数学技巧来完成工作,并且
  • 在您无法假设2s补码的底层实现,但仍希望以这种方式“思考”的情况下工作。(尝试在PHP中“存储”位掩码,并认为它们可以在PHP中工作)
  • 请阅读评论并实施@Paebbels解决方案。性能上的差异几乎是7倍,因此只有在不经常使用的情况下才使用它

    它利用
    base\u 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";
        }
    }
    
    输出:

    14是1

    15是1

    作为一项功能:

    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]=>三个 =>四个 [2] =>七 )


    我已经实现了一个适合您需要的功能,另外:

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

    • 保存值而不仅仅是索引


    函数提取掩码($mask,&$idxs,&$value){
    
    对于($i=0,$valueToCompare=1,$valueToCompare=1;$valueToCompare抱歉,但是这个解决方案对于一个简单的位移位和位比较的工作消耗了大量的内存和CPU周期。内存量?对于32位整数掩码来说不是太坏。除非您有实时要求(…在PHP中…)或者你反复调用这个,那么这个解决方案是合适的。否则,我相信人们会发现你的答案很有用。我的解决方案:3 wordsá4 bytes=12 bytes{m,j,I},它没有调用指令。--你的解决方案将掩码从int转换为字符串;使用基于双值的基转换(字符串到双精度、基转换、到字符串转换);之后是字符串操作(str_split)使用,最后是字符串反转操作。这些只是初始的滑行…在每次迭代中,您访问哈希列表并调用isset函数进行简单的位比较。您的代码使用35条调用指令。内存:中间字符串的每个字符存储在2个字节(UTF-16)中=>64字节。更新后,该方法的警告更加明确。希望@Nikola Obreshkov能够返回并重新思考。我已经实施了该解决方案,并且效果良好。我必须承认,从算法角度来看,第二个答案似乎更有效。对于任何感兴趣的人来说,实际使用方法是在巢穴中标记治疗过的牙齿tal image。当你提供的都是伪代码而没有解决张贴的问题时,你怎么能批评Jeff Lambert的真实PHP代码?正如Jeff所指出的,我提出的算法(他实现的)快了7倍!这甚至不是PHP
    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);