9

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

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

4

3 回答 3

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
于 2014-12-17T22:11:54.030 回答
2

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

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

  • 保存值而不仅仅是索引


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>

于 2019-01-27T08:22:00.250 回答
1

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

  1. 它是明确的,使用文字而不是数学技巧来完成工作,并且
  2. 适用于您无法假设 2s 补码的底层实现,但仍想以这种方式“思考”的情况。(尝试在 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";
    }
}

输出:

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

于 2014-12-17T22:14:59.590 回答