C 中的按位运算:无法弄清楚为什么 XOR 不起作用。我的代码或逻辑有缺陷吗?
Bitwise Operations in C: Can't figure out why XOR does not work. Is my code or logic flawed?
我只能使用下面提到的位运算符来创建描述的函数:
/*
* allEvenBits - return 1 if all even-numbered bits in word set to 1
* Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
我们使用 2s 补码,整数的 32 位表示。此外,我只能使用 0 到 255 (0xFF) 之间的整数常量,包括在内。我的暴力解决方案如下:
int allEvenBits(int x) {
int mask0 = 0x55;
int mask1 = 0x55 << 8;
int mask2 = 0x55 << 16;
int mask3 = 0x55 << 24;
return(!(x ^ (mask0 | mask1 | mask2 | mask3)));
}
所以我基本上创建了一个 0x55555555 掩码,将掩码与 x 进行异或运算,并假设唯一一次 (x ^ 0x55555555)
等于 0 是 x 等于 0x55555555 时否定此操作。 (基于 x ^ x == 0
的 XOR 属性。)
因此,当x == 0x55555555
时,这应该是我函数returns 1的唯一时间。当x == 0x55555555
.[=16=时它确实return 1 ]
但是,我的功能不正确,我也不知道为什么。是我的逻辑有问题还是我的代码?
按照问题陈述而不是你的处方,函数应该只 return 1 for 0x55555555,这是一种方法:
int allEvenBits(int x) {
int filled = x | 0xAAAAAAAA;
return !(filled + 1);
}
我们将输入与设置了所有奇数位的值按位或运算。因此,如果输入中的所有偶数位都已设置,我们将得到 0xFFFFFFFF。然后我们递增 1 溢出并得到 0,最后我们取反得到结果。增加除 0xFFFFFFFF 之外的任何数字将给出非零结果,当取反时将为 0。
// Get a platform-independent mask of all even bits in an int set to one:
#define MASK ( (unsigned int) 0x55555555u )
/* MASK will be 0x5555u or 0x55555555u depending on sizeof(int).
And then the actual algorithm: */
unsigned int allEvenBits(int x)
{
return (unsigned int)( !(x ^ MASK) );
}
你正在切换偶数位,然后将结果与 0 进行比较。但是,即使所有偶数位都为 1,奇数位仍保持不变,因此每当奇数位为 1 时,你的函数将 return 0.只有奇数位全为0才能正常工作
return (!(x ^ (mask0 | mask1 | mask2 | mask3)));
您需要清除所有奇数位
int allEvenBits(int x) {
int mask = 0x55;
int mask = mask | (mask << 8);
int mask = mask | (mask << 16);
return !(x & mask);
}
另一种方式
int allEvenBits(int x) {
int mask = 0xAA;
int mask = mask | (mask << 8);
int mask = mask | (mask << 16);
return !((x | mask) ^ (~0));
}
另一条更短的路
x &= x >> 16;
x &= x >> 8;
return !((x & 0x55) ^ 0x55);
// or return !(((x | 0xAA) + 1) & 0xFF);
我只能使用下面提到的位运算符来创建描述的函数:
/*
* allEvenBits - return 1 if all even-numbered bits in word set to 1
* Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
我们使用 2s 补码,整数的 32 位表示。此外,我只能使用 0 到 255 (0xFF) 之间的整数常量,包括在内。我的暴力解决方案如下:
int allEvenBits(int x) {
int mask0 = 0x55;
int mask1 = 0x55 << 8;
int mask2 = 0x55 << 16;
int mask3 = 0x55 << 24;
return(!(x ^ (mask0 | mask1 | mask2 | mask3)));
}
所以我基本上创建了一个 0x55555555 掩码,将掩码与 x 进行异或运算,并假设唯一一次 (x ^ 0x55555555)
等于 0 是 x 等于 0x55555555 时否定此操作。 (基于 x ^ x == 0
的 XOR 属性。)
因此,当x == 0x55555555
时,这应该是我函数returns 1的唯一时间。当x == 0x55555555
.[=16=时它确实return 1 ]
但是,我的功能不正确,我也不知道为什么。是我的逻辑有问题还是我的代码?
按照问题陈述而不是你的处方,函数应该只 return 1 for 0x55555555,这是一种方法:
int allEvenBits(int x) {
int filled = x | 0xAAAAAAAA;
return !(filled + 1);
}
我们将输入与设置了所有奇数位的值按位或运算。因此,如果输入中的所有偶数位都已设置,我们将得到 0xFFFFFFFF。然后我们递增 1 溢出并得到 0,最后我们取反得到结果。增加除 0xFFFFFFFF 之外的任何数字将给出非零结果,当取反时将为 0。
// Get a platform-independent mask of all even bits in an int set to one:
#define MASK ( (unsigned int) 0x55555555u )
/* MASK will be 0x5555u or 0x55555555u depending on sizeof(int).
And then the actual algorithm: */
unsigned int allEvenBits(int x)
{
return (unsigned int)( !(x ^ MASK) );
}
你正在切换偶数位,然后将结果与 0 进行比较。但是,即使所有偶数位都为 1,奇数位仍保持不变,因此每当奇数位为 1 时,你的函数将 return 0.只有奇数位全为0才能正常工作
return (!(x ^ (mask0 | mask1 | mask2 | mask3)));
您需要清除所有奇数位
int allEvenBits(int x) {
int mask = 0x55;
int mask = mask | (mask << 8);
int mask = mask | (mask << 16);
return !(x & mask);
}
另一种方式
int allEvenBits(int x) {
int mask = 0xAA;
int mask = mask | (mask << 8);
int mask = mask | (mask << 16);
return !((x | mask) ^ (~0));
}
另一条更短的路
x &= x >> 16;
x &= x >> 8;
return !((x & 0x55) ^ 0x55);
// or return !(((x | 0xAA) + 1) & 0xFF);