1

所以,我有从 0 到 15 的数值,所以我将它们保存为十六进制代码(0 到 f)。现在我有一串数据,其中包含我的半字节的十六进制代码值。

数据如下所示:

a0fc3d78270db962e4ba525cf3acd

在两个半字节上执行二进制异或的准确/优雅/快速方法是什么?在半字节上执行二进制的最快方法是什么?

我现在想到的是首先将半字节转换为完整字节:

$nibble = "c";
$numeric = ord($nibble);
$byte = ($numeric<58)?chr($numeric-48):chr($numeric-55);

然后对这些字节执行所需的操作(异或或不),并再次将结果值重新转换为半字节。

$byte1 = chr(7); $byte2=chr(12);
$xor_val = $byte1 ^ $byte2;
$numeric = ord($xor_val);
$nibble = ($numeric<58)?chr($numeric+48):chr($numeric+55);

这种方法的问题是,如果我对一个字节应用 not (~) 操作,它也会反转前 4 位(因此将 1111 添加到半字节的左侧),我必须进入额外的复杂性从结果的 ord() 值中减去 240,然后我使用上面提供的代码将其重新转换为半字节。这不仅让以后的代码升级变得很麻烦,而且也让以后更难解释代码的功能。

执行按位异或而不是半字节并将结果值作为十六进制代码(字符串)的最佳/准确方法是什么?

例子:

'3' xnor 'a' = '6'  
'c' xnor '5' = '6'  
'b' xnor '8' = 'c'
4

1 回答 1

1

使用二进制 AND 操作仅选择相关位:

$nibble1 = hexdec('3');
$nibble2 = hexdec('a');

// nibble1 xnor nibble2
$r = ~($nibble1 ^ $nibble2) & 0x0F;

echo dechex($r); // '6'

这称为“屏蔽掉”位,这里0x0F称为“屏蔽”。

如果没有屏蔽,操作的结果~(0x0b ^ 0x08)将是ffffffffffffffffc,因为 PHP 将整数表示为 64 位长整数。

现在,当我们应用掩码时,会发生以下情况(为了便于可视化,我省略了高 4 个字节):

11111111 11111111 11111111 11111100 (ffffffffc)
00000000 00000000 00000000 00001111 (00000000f)
----------------------------------- & (binary AND)
00000000 00000000 00000000 00001100 (00000000c)

我们只“选择”较低的最后一个半字节。

要屏蔽上半字节,请使用0xF0并(可选)右移 4。

$byte1 = hexdec('3f');
$byte2 = hexdec('a5');

$r = (~($byte1 ^ $byte2) & 0xF0) >> 4;

echo dechex($r); // Also '6'
于 2018-08-01T19:03:53.980 回答