将 32 位整数与自身异或
XORing a 32 bit integer with itself
我坚持用它本身对一个 32 位整数进行异或运算。我应该对整数的 4 个 8 位部分进行异或运算。我了解它是如何工作的,但是如果不在任何地方存储整数,我不知道该怎么做。
我想了想,正在考虑使用二进制左移和右移运算符将32位整数分成4个部分进行异或。例如,如果我要使用一个 8 位整数,我会这样做:
int a = <some integer here>
(a << 4) ^ (a >> 4)
到目前为止,它并没有像我想象的那样工作。
这是我的部分代码:
else if (choice == 2) {
int bits = 8;
printf("Enter an integer for checksum calculation: ");
scanf("%d", &in);
printf("Integer: %d, ", in);
int x = in, i;
int mask = 1 << sizeof(int) * bits - 1;
printf("Bit representation: ");
for (i = 1; i <= sizeof(int) * bits; i++) {
if (x & mask)
putchar('1');
else
putchar('0');
x <<= 1;
if (! (i % 8)) {
putchar(' ');
}
}
printf("\n");
}
这是一个输出示例:
What type of display do you want?
Enter 1 for character parity, 2 for integer checksum: 2
Enter an integer for checksum calculation: 1024
Integer: 1024, Bit representation: 00000000 00000000 00000100 00000000
Checksum of the number is: 4, Bit representation: 00000100
要累加 8 位值的异或,您只需对值的每一部分进行移位和异或。从概念上讲是这样的:
uint32_t checksum = ( (a >> 24) ^ (a >> 16) ^ (a >> 8) ^ a ) & 0xff;
但是,由于 XOR 可以按任何顺序进行,因此您可以用更少的操作来完成相同的操作:
uint32_t checksum = (a >> 16) ^ a;
checksum = ((checksum >> 8) ^ checksum) & 0xff;
如果您对许多值执行此操作,则可以通过仅在最后压缩值来扩展此想法。这与使用 SIMD 等技术在较大寄存器中完成并行交换操作的方式非常相似(事实上,支持 SIMD 的编译器应该能够优化以下代码以使其更快):
uint32_t simple_checksum( uint32_t *v, size_t count )
{
uint32_t checksum = 0;
uint32_t *end = v + count;
for( ; v != end; v++ )
{
checksum ^= *v; /* accumulate XOR of each 32-bit value */
}
checksum ^= (checksum >> 16); /* XOR high and low words into low word */
checksum ^= (checksum >> 8 ); /* XOR each byte of low word into low byte */
return checksum & 0xff; /* everything from bits 8-31 is rubbish */
}
一般来说,将一个数与自身进行异或运算应该会为您提供值 0,这样您就可以轻松地将变量设置为 0。
0100101^0100101=0
这是异或运算的卡诺图的结果,当两个位均为 1 或均为 0 时提供 0。
我坚持用它本身对一个 32 位整数进行异或运算。我应该对整数的 4 个 8 位部分进行异或运算。我了解它是如何工作的,但是如果不在任何地方存储整数,我不知道该怎么做。
我想了想,正在考虑使用二进制左移和右移运算符将32位整数分成4个部分进行异或。例如,如果我要使用一个 8 位整数,我会这样做:
int a = <some integer here>
(a << 4) ^ (a >> 4)
到目前为止,它并没有像我想象的那样工作。
这是我的部分代码:
else if (choice == 2) {
int bits = 8;
printf("Enter an integer for checksum calculation: ");
scanf("%d", &in);
printf("Integer: %d, ", in);
int x = in, i;
int mask = 1 << sizeof(int) * bits - 1;
printf("Bit representation: ");
for (i = 1; i <= sizeof(int) * bits; i++) {
if (x & mask)
putchar('1');
else
putchar('0');
x <<= 1;
if (! (i % 8)) {
putchar(' ');
}
}
printf("\n");
}
这是一个输出示例:
What type of display do you want?
Enter 1 for character parity, 2 for integer checksum: 2
Enter an integer for checksum calculation: 1024
Integer: 1024, Bit representation: 00000000 00000000 00000100 00000000
Checksum of the number is: 4, Bit representation: 00000100
要累加 8 位值的异或,您只需对值的每一部分进行移位和异或。从概念上讲是这样的:
uint32_t checksum = ( (a >> 24) ^ (a >> 16) ^ (a >> 8) ^ a ) & 0xff;
但是,由于 XOR 可以按任何顺序进行,因此您可以用更少的操作来完成相同的操作:
uint32_t checksum = (a >> 16) ^ a;
checksum = ((checksum >> 8) ^ checksum) & 0xff;
如果您对许多值执行此操作,则可以通过仅在最后压缩值来扩展此想法。这与使用 SIMD 等技术在较大寄存器中完成并行交换操作的方式非常相似(事实上,支持 SIMD 的编译器应该能够优化以下代码以使其更快):
uint32_t simple_checksum( uint32_t *v, size_t count )
{
uint32_t checksum = 0;
uint32_t *end = v + count;
for( ; v != end; v++ )
{
checksum ^= *v; /* accumulate XOR of each 32-bit value */
}
checksum ^= (checksum >> 16); /* XOR high and low words into low word */
checksum ^= (checksum >> 8 ); /* XOR each byte of low word into low byte */
return checksum & 0xff; /* everything from bits 8-31 is rubbish */
}
一般来说,将一个数与自身进行异或运算应该会为您提供值 0,这样您就可以轻松地将变量设置为 0。
0100101^0100101=0
这是异或运算的卡诺图的结果,当两个位均为 1 或均为 0 时提供 0。