Сравнение двух строк, ограниченных битовой маской в ​​PHP

В некоторых PHP мне нужно сравнить две строки, но только по битам, которые установлены как один в битовой маске. Как бы я реализовал такое поведение?

Я пробовал:

$string1='aaabbb';
$string2='ababbb';
$bitmask='101101';
function compare($string1, $string2, $bitmask){
    $resultBitmask=(~($string1 ^ $string2)|~$bitmask);
} 

Для ясности я записал ff байта как 1 в битовой маске для иллюстративных целей. На самом деле они будут ff в шестнадцатеричном формате при создании битовой маски. То же самое касается 0 нулевых байтов.

Строка и битовая маска всегда имеют разную длину при каждом вызове функции. Мне удалось получить набор бит для сравнения, но я не могу проверить, все ли они установлены, так как длина различается. В настоящее время я использую preg_match с регулярным выражением, которое соответствует любому количеству ff байтов, но есть ли более элегантное решение?

Редактировать: поскольку строки имеют длину до 4096 бит, их нельзя преобразовать в числа.


person nanofarad    schedule 24.10.2012    source источник
comment
Я думаю, вам придется преобразовать их в числа.   -  person jarchuleta    schedule 25.10.2012
comment
@jarchuleta Я бы хотел, но они могут быть до 4 КБ.   -  person nanofarad    schedule 25.10.2012
comment
вы можете найти большую библиотеку номеров. или конвертируйте их побайтно, а затем сравните.   -  person jarchuleta    schedule 25.10.2012
comment
@jarchuleta Код полностью переносим на веб-хосты, которые могут не иметь гигантских библиотек чисел. Что касается второй идеи, можете ли вы добавить полный ответ по этому поводу?   -  person nanofarad    schedule 25.10.2012


Ответы (2)


Это не самый быстрый способ сделать это, но:

$stillTheSame = true;
for($i=0;$i<=strlen($bitmask); $i++)
{
  if($bitmask[$i] == 1)
  {
    if($string1[$i] != $string2[$i]) 
    {
      $stillTheSame = false;
      break;
    }  
  }
}

Не уверен в вашей фактической логике проверки, но, надеюсь, это должно помочь.

person Martin Lyne    schedule 24.10.2012
comment
Разве это не больше обход, чем рекурсия? Но, тем не менее, мне приходится работать с другими разработчиками, и часто я предпочитаю писать что-то легко читаемое, чем объяснять это всем каждый раз, когда они на это смотрят. Все для легкой жизни.. - person Martin Lyne; 25.10.2012
comment
Извините, у меня плохо с терминологией. Это действительно обход. - person nanofarad; 25.10.2012
comment
Это хороший ответ, но, к сожалению, кажется, что он занимает больше секунды для 1000 итераций со строкой из 160 байтов. Извини. - person nanofarad; 25.10.2012
comment
Не для скорости, правда. Всегда ли это 1 битовая маска для 2 строк или 1 байт-код для сравнения большого количества строк? - person Martin Lyne; 25.10.2012
comment
Re: Ваш последний комментарий. Я переписал некоторый окружающий код, чтобы одна и та же битовая маска применялась ко многим строкам, но между каждым запуском тысяч строк ему потребуется новая битовая маска и длина. - person nanofarad; 28.10.2012
comment
Я спрашивал только потому, что думал, что вы сможете сначала пройти через маску, создать массив из strpos каждой «1», а затем использовать его для прямой ссылки на требуемые позиции символов string1/2. Но я все еще не думаю, что это совсем то, что вы ищете. Просто потенциально ускоряет мою медленную версию. Я мог бы еще раз взглянуть на ваш вопрос, пытаясь использовать побитовую жесткость, я невероятно ржавый с этим. - person Martin Lyne; 28.10.2012
comment
Я действительно нашел решение. Смотрите ниже, и спасибо за помощь! - person nanofarad; 29.10.2012

Самостоятельное решение:

Поскольку это будет повторяться со многими строками одинаковой длины во время выполнения, но иметь разную длину между запусками, мне нужно проверить, что результирующая строка после побитовых операций — это все единицы и правильная длина. Я понял, что эта строка, полная единиц, может быть сгенерирована при необходимости, что происходит довольно редко, примерно раз в 1000 сравнений строк. Я могу сгенерировать строку перед запуском следующим образом:

$ones=str_repeat(chr(255), $byte_length);

а затем определить функцию compare( немного по-другому:

function compare($string1, $string2, $bitmask){
    global $ones;
    $resultBitmask=(~($string1 ^ $string2)|~$bitmask);
    if ($resultBitmask=$ones){
         return 1;
    } else {return 0};
} 

Хитрость заключалась в том str_repeat, о котором я раньше не знал.

person nanofarad    schedule 28.10.2012