我有一个用于位掩码的 32 位整数和一个具有 32 个值的数组。如何从数组中仅获取那些索引对应于位掩码中非零位位置的值?
例如,假设位掩码是 49152,即二进制 1100000000000000。因此,我必须从数组中获取索引为 14 和 15 的元素的值。
我有一个用于位掩码的 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
我已经实现了一个满足您需求的功能,此外:
可以处理更小或更大的数据类型
保存值而不仅仅是索引
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>
这里有一些 PHP 代码给你,但请注意它效率很低。我使用这个算法是因为:
请阅读评论并实施@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] => 七)