假设我有这两个数字:
x = 0xB7
y = 0xD9
他们的二进制表示是:
x = 1011 0111
y = 1101 1001
现在我想在给定点交叉(GA),比如从第4位开始。
预期结果应为:
x = 1011 1001
y = 1101 0111
按位,我怎么能实现这个目标?
答案 0 :(得分:2)
我只想使用按位运算符:
t = (x & 0x0f)
x = (x & 0xf0) | (y & 0x0f)
y = (y & 0xf0) | t
这适用于该特定情况。为了使它更具适应性,我将它放在一个函数中,例如:
def swapBits (x, y, s, e):
lookup = [255,127,63,31,15,7,3,1]
mask = lookup[s] & !lookup[e]
t = x & mask
x = (x & !mask) | (y & mask)
y = (y & !mask) | t
return (x,y)
查找值允许您指定要交换的位。我们将xxxxxxxx
和x
的值yyyyyyyy
与y的起始位s
和6的结束位e
取得一致(位数从零开始)在这个场景的左边。)
x y s e t mask !mask execute
-------- -------- - - -------- -------- -------- -------
xxxxxxxx yyyyyyyy 2 6 starting point
00111111 mask = lookup[2](00111111)
00111100 & !lookup[6](11111100)
00xxxx00 t = x & mask
xx0000xx x = x & !mask(11000011)
xxyyyyxx | y & mask(00111100)
yy0000yy y = y & !mask(11000011)
yyxxxxyy | t(00xxxx00)
答案 1 :(得分:0)
Swapping individual bits with XOR
unsigned int i, j; // positions of bit sequences to swap
unsigned int n; // number of consecutive bits in each sequence
unsigned int b; // bits to swap reside in b
unsigned int r; // bit-swapped result goes here
unsigned int x = ((b >> i) ^ (b >> j)) & ((1U << n) - 1); // XOR temporary
r = b ^ ((x << i) | (x << j));
答案 2 :(得分:0)
如果两个值中的位位置相同,则两者中都不需要进行任何更改。如果相反,他们都需要反转。
XOR,1次翻转; XOR为0是无操作。
所以我们想要的是一个值1
,到处输入之间有点差异,其他地方都是0。这正是a XOR b
所做的。
只需屏蔽这个位差,只保留我们想要交换的位的差异,我们在3个XOR + 1 AND中进行位交换。
你的面具是(1UL << position) -1
。比2的幂小一个的所有位都低于该值。或者更常见的是您的位范围的高位和低位:(1UL << highpos) - (1UL << lowpos)
。查找表是否比位集/子更快取决于编译器和硬件。 (参见@ PaxDiablo对LUT建议的回答)。
// Portable C:
//static inline
void swapBits_char(unsigned char *A, unsigned char *B)
{
const unsigned highpos = 4, lowpos=0; // function args if you like
const unsigned char mask = (1UL << highpos) - (1UL << lowpos);
unsigned char tmpA = *A, tmpB = *B; // read into locals in case A==B
unsigned char bitdiff = tmpA ^ tmpB;
bitdiff &= mask; // clear all but the selected bits
*A = tmpA ^ bitdiff; // flip bits that differed
*B = tmpB ^ bitdiff;
}
//static inline
void swapBit_uint(unsigned *A, unsigned *B, unsigned mask)
{
unsigned tmpA = *A, tmpB = *B;
unsigned bitdiff = tmpA ^ tmpB;
bitdiff &= mask; // clear all but the selected bits
*A = tmpA ^ bitdiff;
*B = tmpB ^ bitdiff;
}
(Godbolt compiler explorer with gcc for x86-64 and ARM)
不是xor-swap 。它确实使用临时存储。正如近似重复问题上的@chux's answer所示,屏蔽的xor-swap需要3个AND运算以及3个XOR。 (并且通过要求&
结果的临时注册或其他存储来抵消XOR交换的唯一好处。)这个答案是我在另一个问题上的答案的修改副本。
此版本仅需要1 AND。此外,最后两个XOR彼此独立,因此从输入到两个输出的总延迟仅为3个操作。 (通常为3个周期)。
对于x86 asm示例,请参阅此代码-golf Exchange capitalization of two strings in 14 bytes of x86-64 machine code(带注释的asm源代码)