旧问题名称:如何在10,0,11组中有效地拆分二进制字符串?
我有一些字符串作为输入,它是数字的二进制表示。 例如:
10011
100111
0111111
11111011101
我需要将这些字符串(或数组)拆分为10,0和11组,以便替换它们。
10 => 11
0 => 0
11 => 10
怎么做?我尝试过这些选项但不起作用。
preg_match('/([10]{2})(0{1})([11]{2})/', $S, $matches);
10011输入应为[10] [0],[11]。 更换时应该是11010。
UPD1。
实际上,我正在尝试做一个否定算法,用于将基数-2中的正数转换为基数-2中的负数。 它可以通过维基百科的循环算法来完成。但是字节组替换要快得多。我已经实现了它,只是尝试优化它。
对于这种情况0111111
,最终可以添加0。然后将应用规则。我们可以删除结果中的前导零。输出将是101010。
UPD2。
@WiktorStribiżew提出了一个如何立即进行替换的想法,而不是先将字节分成组。 但我已经有了更快的解决方案。
$S = strtr($S, $rules);
这个问题的意思不是替代,而是获得一系列所需的群体[11] [0] [10]。
UPD3。
这是一个我想到的转换二进制组的解决方案。它比带环的速度快。
function solution2($A)
{
$S = implode('', $A);
//we could add leading 0
if (substr($S, strlen($S) - 1, 1) == 1) {
$S .= '0';
}
$rules = [
'10' => '11',
'0' => '0',
'11' => '10',
];
$S = strtr($S, $rules);
$arr = str_split($S);
//remove leading 0
while ($arr[count($arr) - 1] == 0) {
array_pop($arr);
}
return $arr;
}
但@Alex Blex答案中的解决方案更快。
答案 0 :(得分:3)
您可以使用简单的/11|10/
正则表达式与preg_replace_callback
:
$s = '10011';
echo preg_replace_callback("/11|10/", function($m) {
return $m[0] == "11" ? "10" : "11"; // if 11 is matched, replace with 10 or vice versa
}, $s);
// => 11010
请参阅online PHP demo。
答案 1 :(得分:1)
回答问题
用于将基数-2中的正数转换为基数-2
中的负数的算法
我相信以下功能比正则表达式更有效:
function negate($negabin)
{
$mask = 0xAAAAAAAAAAAAAAA;
return decbin((($mask<<1)-($mask^bindec($negabin)))^$mask);
}
参数是基数-2表示法中的正int60,例如11111011101。
该函数将参数转换为基数10,否定它,并将其转换回基数-2,如维基中所述:https://en.wikipedia.org/wiki/Negative_base#To_negabinary
适用于64位系统,但可以轻松采用32位工作。