Получить значения массива на основе битовой маски в PHP
у меня есть 32-разрядное целое число, используемое для битовой маски и массива с 32 значениями. Как получить из массива только те значения, индексы которых соответствуют позициям ненулевых битов в битовой маске?
например, допустим, что битовая маска равна 49152, которая равна 1100000000000000 в двоичном формате. Поэтому я должен взять значения элементов с индексами 14 и 15 из массива.
2 ответов
вот вам PHP-код, но обратите внимание, что он довольно неэффективен. Я использовал этот алгоритм, потому что:
- это явное и использует слова, а не математические трюки, чтобы получить работу, и
- работает в ситуациях, когда вы не можете предположить базовую реализацию дополнения 2s, но все же хотите "думать" таким образом. (попробуйте "хранить" битовые маски в PHP и думать, что они будут работать в JavaScript)
пожалуйста, прочитайте комментарии и реализовать решение @Paebbels. Разница в производительности почти 7x, поэтому действительно используйте это, если он не будет использоваться очень часто.
Он использует base_convert
чтобы преобразовать целое число base 10 в base 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] => три 1 => четыре [2] => Семь )
вам нужно будет выполнить цикл в 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