Как получить набор числовых рядов из двух битов 16-битного int?


(Работа над алгоритмом поиска) Я хочу перебрать возможные совпадения с двумя битами, установленными в 16-битном слове. Кажется глупой проблемой с чрезмерно сложным в настоящее время решением.

Итерация должна возвращать (десятичное число) 3,5,6,9,10,12,17...

Какое подходящее слово для этой проблемы? Зацикливание на битовой маске? Есть какая-нибудь умная функция для этого?

Текущий код - теперь обновлен: (Как бы то ни было, я думаю, что нет более простого способа обойти это.)

<?php

function biterate($numBits=8, $setBits=2, $maxval=null) {
  //init
  if(is_null($maxval)) $maxval = (pow(2,$setBits)-1) * pow(2,$numBits - $setBits);
  $err = 0;
  header('content-type:text/plain');
  echo '-- ' . $setBits . ' of ' . $numBits . " --\r\n";
  $result = str_pad('', $numBits - $setBits, '0') . str_pad('', $setBits, '1');
  do {
    $err++;
    if($err > 200) die('bad code');
    //echo and calc next val.
    echo $result . ' : ' . bindec($result) . "\r\n";
    //count set bits and search for '01' to be replaced with '10'. From LSB.
    $bitDivend = '';
    $hit = false;
    for($i=$numBits;$i>0;$i--) {
      if(substr($result,$i-2,2) == '01') {
          $hit = true;
          //do the replacement and replace the lower part with bitDivend.
          $result = substr($result, 0, $i-2) . '10';
          $result .= str_pad('',$numBits - $i - strlen($bitDivend),'0');
          $result .= $bitDivend;
          //exit loop
          $i = 0;
      }
      if($result[$i-1] == '1') $bitDivend .= '1';
    }
  } while($hit && bindec($result) <= $maxval);      
}

biterate(8,2);
biterate(8,7);


biterate();
Author: Teson, 2017-05-04

1 answers

Если вы просто хотите, чтобы все 16-битные входы были установлены с 2 битами, это должен сделать следующий код:

<?php
for($i=1;$i<16;$i++)
{
    for($j=0;$j<$i;$j++)
    {
        echo (1<<$i)|(1<<$j) , "\r\n";
    }
}
?>

Если вы посмотрите на битовые шаблоны чисел, вы увидите, как это работает:

   11    3

  101    5
  110    6

 1001    9
 1010   10
 1100   12

10001   17
10010   18
10100   20
11000   24

И т.д. Вы просто перемещаете наиболее значимый бит на одно место влево (другая степень 2) для каждой итерации внешнего цикла, а внутри внутреннего цикла вы повторяете от наименее значимого бита (1) до 1 места справа от наиболее значимого бита.

Если вы хотите обобщить это позволяет поддерживать произвольное количество битов и мест, вы можете расширить описанный выше алгоритм с помощью рекурсии:

<?php
function biterate_recursive($numBits=8, $setBits=2, $initialValue=0, $maxval=null) {
    for($i=$setBits-1;$i<$numBits;$i++)
    {
        if(!is_null($maxval) && ($initialValue|(1<<$i)) > $maxval)
            break;

        if($setBits==1)
            echo $initialValue|(1<<$i) , "\r\n";
        else
            biterate_recursive($i, $setBits-1, $initialValue|(1<<$i), $maxval);
    }
}

biterate_recursive(16, 2);
?>

Вы также можете думать о проблеме как о простом выборе комбинаций, т.Е. C(16,2) выбирает 2 числа a, b из набора 0-15, а затем вычисляет (1<<a)|(1<<b). Однако вы должны быть осторожны с выбором алгоритма комбинации, если хотите расположить числа по порядку.

 1
Author: samgak, 2017-05-06 23:40:31