簡體   English   中英

如何檢查值是否具有偶數奇偶校驗位或奇數?

[英]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 位整數,我們可以跳過前兩個移位/異或。 讓我們標記位ah 如果我們查看我們的號碼,我們會看到:

) ( )


第一個操作是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 longunsigned 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

現在x1100 x & ( x - 1 )1100 & 1011的運算是1000 請注意,原始x1101並且在x & (x - 1)的兩次操作之后x1000 ,即在兩次操作之后刪除了兩個設置位。 如果經過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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM