web-dev-qa-db-ja.com

値にビットの偶数パリティまたは奇数があるかどうかを確認するにはどうすればよいですか?

1ビットの偶数の値は、パリティが偶数になります。値が奇数の1ビットの場合、値は奇数パリティになります。例えば、 0110は偶数のパリティを持ち、1110には奇数のパリティがあります。

返さなければなりません1xが偶数の場合。

int has_even_parity(unsigned int x) {
    return 
}
11
Manuel

試してください:

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;
}

valter

x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return (~x) & 1;

あなたがintが32ビットであることを知っていると仮定します。


これがどのように機能するか見てみましょう。簡単にするために、8ビット整数を使用します。最初の2つのシフト/ XORをスキップできます。ビットにラベルを付けましょうaからhまで。番号を見ると、次のことがわかります。

( abcdefgh


最初の操作はx ^= x >> 4(この例では8ビット整数しか扱っていないため、最初の2つの操作はスキップしています)。 XORされた文字を組み合わせて、各ビットの新しい値を書きましょう(たとえば、 ab ビットが値を持つことを意味します a XOR b)。

( abcdefgh )xor( abcd

結果は次のビットです。

( abcdaebFcgdh


次の操作はx ^= x >> 2

( abcdaebFcgdh )xor(0 0 abcdaebF

結果は次のビットです。

( ab交流bdエースbdfacegbdfh

右側にすべてのビットが蓄積され始めていることに注意してください。


次の操作はx ^= x >> 1

( ab交流bdエースbdfacegbdfh )xor(0 ab交流bdエースbdfaceg

結果は次のビットです。

( aabaBCあいうえおabcdeabcdefabcdefgabcdefgh


元のワードのすべてのビットをXORして、最下位ビットに累積しました。したがって、入力ビットに偶数個の1ビット(偶数パリティ)が存在する場合にのみ、このビットはゼロになります。同じプロセスが32ビット整数でも機能します(ただし、このデモでスキップした2つの追加シフトが必要です)。

コードの最後の行では、最下位ビット(& 1)と反転します(~x)。結果は、入力ワードのパリティが偶数の場合は1、それ以外の場合は0になります。

65
TypeIA

次の回答は、恥ずかしがらずに Bit Twiddling Hacks By Sean Eron Anderson、seander @ cs.stanford.ed から直接取り上げられました。

Wordのパリティを乗算で計算します

次のメソッドは、乗算を使用して32ビット値のパリティを8つの演算のみで計算します。

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;

アンドリューシャピラがこれを思いついて、2007年9月2日に送ってくれました。

6
Troyseph

GCCには 組み込み関数 があります:

組み込み関数:int __builtin_parity (unsigned int x)

xのパリティ、つまり2を法とするxの1ビットの数を返します。

つまりこの関数はhas_odd_parityのように動作します。 has_even_parityの値を反転します。

これは、GCCの最速の代替手段であることが保証されています。もちろん、その使用自体は移植可能ではありませんが、たとえばマクロで保護された実装で使用できます。

5
Antti Haapala

@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);
}
1
Rishav Ambasta

主なアイデアはこれです。 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)の2つの演算の後、xは_1000_になります。つまり、2つのセットビットが2つ後に削除されます。操作。 odd回の操作の後、xがゼロになると、奇数パリティーになり、それ以外の場合は偶数パリティーになります。

1
madhu sudhan

これが1行_#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関数バージョン、inline char parity(char x) {return PARITY(x);}(GCC)または__inline char parity(char x) {return PARITY(x);}(MSVC)を使用しても同じ効率が得られます。 1行の定義を維持するとします。

0
Danny Holstein
int parity_check(unsigned x) {
    int parity = 0;
    while(x != 0) {
        parity ^= x;
        x >>= 1;
    }
    return (parity & 0x1);
}
0