1ビットの偶数の値は、パリティが偶数になります。値が奇数の1ビットの場合、値は奇数パリティになります。例えば、 0110
は偶数のパリティを持ち、1110
には奇数のパリティがあります。
返さなければなりません1
x
が偶数の場合。
int has_even_parity(unsigned int x) {
return
}
試してください:
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になります。
次の回答は、恥ずかしがらずに 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日に送ってくれました。
GCCには 組み込み関数 があります:
組み込み関数:
int __builtin_parity (unsigned int x)
x
のパリティ、つまり2を法とするxの1ビットの数を返します。
つまりこの関数はhas_odd_parity
のように動作します。 has_even_parity
の値を反転します。
これは、GCCの最速の代替手段であることが保証されています。もちろん、その使用自体は移植可能ではありませんが、たとえばマクロで保護された実装で使用できます。
@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);
}
主なアイデアはこれです。 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行_#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行の定義を維持するとします。
int parity_check(unsigned x) {
int parity = 0;
while(x != 0) {
parity ^= x;
x >>= 1;
}
return (parity & 0x1);
}