[英]How to XOR all of the bits of a single number in C?
有沒有一種簡單的方法可以將單個數字的所有位異或在一起,即 C 中的一元異或?
具有以下效果的東西:
result = ^(0x45); // ( 0 ^ 1 ^ 0 ^ 0 ^ 0 ^ 1 ^ 0 ^ 1 = 1)
result = ^(0x33); // ( 0 ^ 0 ^ 1 ^ 1 ^ 0 ^ 0 ^ 1 ^ 1 = 0)
GCC 有一個內置的:
int xor_bits(unsigned x) {
return __builtin_parity(x);
}
或者,您可以通過計算設置位的數量來計算奇偶校驗。 為此 gcc 內置是__builtin_popcount()
:
int xor_bits(unsigned x) {
return __builtin_popcount(x) & 1;
}
如果您只想堅持使用標准 C,請訪問 https://graphics.stanford.edu/~seander/bithacks.html以及如何計算 32 位整數中設置的位數? 有一些很好的解決方案來計算設置位的數量。
沒有特殊的運算符。 您需要按如下方式手動執行此操作:
unsigned int value = 0x45;
unsigned int result = 0;
while (value) {
result ^= value & 1;
value >>= 1;
}
您還可以創建一個包含所有 1 字節值的奇偶校驗的查找表:
char parity[256] = { 0, 1, 1, 0, 1, 0, 0, 1,
...
1, 0, 0, 1, 0, 1, 1, 0 };
一種簡化的 O(log2(n)) 方法。
#include <limits.h>
int odd_parity(unsigned v) {
#if (UINT_MAX > 0xFFFFFFFFFFFFFFFFu)
v ^= v >> 64; // Prepare for the future
#endif
#if (UINT_MAX > 0xFFFFFFFFu)
v ^= v >> 32;
#endif
#if (UINT_MAX > 0xFFFFu)
v ^= v >> 16;
#endif
v ^= v >> 8;
v ^= v >> 4;
v ^= v >> 2;
v ^= v >> 1;
return (int) (v&1);
}
如果您使用的是 gnu gcc,您應該能夠使用__builtin_popcount來計算 on 位的數量(即位設置為 1)。 XOR 的結果將是這個數字的奇偶校驗。 然而,這個解決方案沒有使用標准,並且不會總是有效。
我相信沒有僅使用標准的優雅解決方案。
如果二進制表示中 1 的數量是奇數,則答案為 1 ; 如果是偶數,則答案為 0
您可以計算循環中的所有位,或者如果您想要一些可能更有效的東西,您可以屏蔽原始數字的一部分並對它們進行異或,重復,直到您得到 1 位操作數。 假設一個 32 位整數用 2 的補碼表示:
int xor_all(int v)
{
int l = (v & 0xFFFF0000) >> 16;
int r = v & 0x0000FFFF;
int m = l ^ r;
l = (m & 0xFF00) >> 8;
r = m & 0x00FF;
m = l ^ r;
l = (m & 0xF0) >> 4;
r = m & 0x0F;
m = l ^ r;
l = (m & 0xC) >> 2;
r = m & 3;
m = l ^ r;
l = (m & 2) >> 1;
r = m & 1;
m = l ^ r;
return m;
}
還有其他技術; 如果您只取結果的最低位,則任何用於計算設置位的良好例程都將起作用。 上面的代碼的好處是比較容易理解,但不太可能是最快的。
試試這個:
unsigned long parity(unsigned long x) {
for(char i=sizeof(unsigned long)<<2;x>1;i>>=1) x=(x^(x<<i))>>i;
return x;
}
unsigned long 是支持的最大類型(unsigned long long 是可能的最大類型)。 它在<cstdint> or <stdint.h>
。 sizeof(unsigned long) 是字節。 我們需要半位開始,所以它是字節*4。 然后,上半部分與下半部分進行異或。 然后我們去掉下半部分。 編輯后的答案保證收斂,最多應該有一個溢出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.