[英]How to check if value has even parity of bits or odd?
如果一個值具有偶數個 1 位,則它具有偶數奇偶性。 如果一個值具有奇數個 1 位,則該值具有奇校驗。 例如, 0110
為偶校驗, 1110
為奇校驗。
如果x
具有偶校驗,我必須返回1
。
int has_even_parity(unsigned int x) {
return
}
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return (~x) & 1;
假設您知道整數是 32 位。
讓我們看看這是如何工作的。 為了簡單起見,讓我們使用一個 8 位整數,我們可以跳過前兩個移位/異或。 讓我們標記位a到h 。 如果我們查看我們的號碼,我們會看到:
) ( )
第一個操作是x ^= x >> 4
(記住我們跳過了前兩個操作,因為在這個例子中我們只處理一個 8 位整數)。 means the bit has the value xor ).讓我們通過將異或運算的字母組合在一起來編寫每個位的新值(例如, 表示該位的值 xor )。
) xor ( ) ( ) xor ( )
結果是以下位:
) ( )
下一個操作是x ^= x >> 2
:
) xor ( 0 0 ) ( ) xor ( 0 0 )
結果是以下位:
) ( )
請注意我們如何開始累積右側的所有位。
下一個操作是x ^= x >> 1
:
) xor ( 0 ) ( ) xor ( 0 )
結果是以下位:
) ( )
我們已將原始字中的所有位累加在一起,並在最低有效位中進行異或運算。 因此,當且僅當輸入字中存在偶數個 1 位(偶數奇偶校驗)時,該位現在為零。 相同的過程適用於 32 位整數(但需要我們在本演示中跳過的那兩個額外的移位)。
最后一行代碼簡單地去除了除最低有效位 ( & 1
) 之外的所有內容,然后將其翻轉 ( ~x
)。 如果輸入字的奇偶校驗為偶數,則結果為 1,否則為 0。
GCC為此具有內置函數:
內置函數:
int __builtin_parity (unsigned int x)
返回
x
的奇偶校驗,即 x 模 2 中 1 位的數量。
以及unsigned long
和unsigned long long
類似函數。
即這個函數的行為類似於has_odd_parity
。 反轉has_even_parity
的值。
這些應該是 GCC 上最快的替代方案。 當然,它的使用本身是不可移植的,但您可以在您的實現中使用它,例如由宏保護。
以下答案直接來自Sean Eron Anderson 的 Bit Twiddling Hacks,seander@cs.stanford.edu
用乘法計算單詞的奇偶校驗
以下方法僅在 8 次運算中使用乘法計算 32 位值的奇偶校驗。
unsigned int v; // 32-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x11111111U) * 0x11111111U;
return (v >> 28) & 1;
同樣對於 64 位,8 次操作仍然足夠。
unsigned long long v; // 64-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x1111111111111111UL) * 0x1111111111111111UL;
return (v >> 60) & 1;
Andrew Shapira 想出了這個並於 2007 年 9 月 2 日寄給我。
嘗試:
int has_even_parity(unsigned int x){
unsigned int count = 0, i, b = 1;
for(i = 0; i < 32; i++){
if( x & (b << i) ){count++;}
}
if( (count % 2) ){return 0;}
return 1;
}
瓦爾特
主要思想是這樣的。 使用x & ( x - 1 )
取消設置最右邊的“1”位。 假設 x = 13(1101) 並且x & ( x - 1 )
的運算是1101 & 1100
也就是 1100,注意最右邊的設置位被轉換為0
。
現在x
是1100
。 x & ( x - 1 )
即1100 & 1011
的運算是1000
。 請注意,原始x
是1101
並且在x & (x - 1)
的兩次操作之后x
是1000
,即在兩次操作之后刪除了兩個設置位。 如果經過odd
數次運算后, x
變為零,則為奇校驗,否則為偶校驗。
概括@TypelA 對任何架構的回答:
int has_even_parity(unsigned int x)
{
unsigned char shift=1;
while (shift < (sizeof(x)*8))
{
x ^= (x>>shift);
shift<<=1;
}
return !(x & 0x1);
}
int parity_check(unsigned x) {
int parity = 0;
while(x != 0) {
parity ^= x;
x >>= 1;
}
return (parity & 0x1);
}
這是一行#define
,它可以解決char
:
#define PARITY(x) ((~(x ^= (x ^= (x ^= x >> 4) >> 2) >> 1)) & 1) /* even parity */
int main()
{
char x=3;
printf("parity = %d\n", PARITY(x));
}
它非常便攜,易於修改以處理更大的單詞(16、32 位)。 還需要注意的是,使用#define
可以加快代碼速度,每個函數調用都需要時間來壓入堆棧並分配內存。 代碼大小不會受到影響,特別是如果它只在您的代碼中實現了幾次 - 函數調用可能會占用與 XOR 一樣多的目標代碼。
誠然,通過使用此的內聯函數版本, inline char parity(char x) {return PARITY(x);}
(GCC) 或__inline char parity(char x) {return PARITY(x);}
(MSVC)。 假設您保持一行定義。
這是一個很老的問題,但我將其發布給將來可能使用它的人。
我不會添加在 c 中執行此操作的示例,因為已經有足夠好的答案。
如果最終結果應該是一段可以與 ac 程序一起工作(編譯)的代碼,那么我建議如下:
.code
; bool CheckParity(size_t Result)
CheckParity PROC
mov rax, 0
add rcx, 0
jnp jmp_over
mov rax, 1
jmp_over:
ret
CheckParity ENDP
END
這是我用來檢查使用 MSVC 編譯的 64 位 c 程序中計算結果的奇偶校驗的一段代碼。 您顯然可以將其移植到 32 位或其他編譯器。
這具有比使用 c 快得多的優點,並且還利用了 cpu 功能。
此示例所做的是將參數作為輸入(在 RCX 中傳遞 - __fastcall 調用約定)。 它將它增加 0,從而設置 cpu 奇偶校驗標志,然后如果奇偶校驗標志打開與否,則將變量 (RAX) 設置為 0 或 1。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.