如何检查值是偶数奇偶校验还是奇数?

如果偶数为1位,则值具有偶校验。 如果具有奇数1位,则该值具有奇校验。 例如, 0110具有偶校验,而1110具有奇校验。

如果x具有偶校验,我必须返回1

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

瓦尔特

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

假设你知道int是32位。


让我们看看它是如何工作的。 为了简单起见,让我们使用一个8位整数,我们可以跳过前两个移位/异或。 让我们标记位ah 。 如果我们查看我们的号码,我们会看到:

a b c d e f g h


第一个操作是x ^= x >> 4 (记住我们正在跳过前两个操作,因为在这个例子中我们只处理一个8位整数)。 让我们通过组合XOR一起的字母来写出每个位的新值(例如, ab表示该位的值为x或b )。

a b c d e f g h )xor( 0 0 0 0 a b c d

结果如下:

a b c d ae bf cg dh


下一个操作是x ^= x >> 2

a b c d ae bf cg dh )xor(0 0 a b c d ae bf

结果如下:

a b ac bd ace bdf aceg bdfh

注意我们如何开始累积右侧的所有位。


下一个操作是x ^= x >> 1

a b ac bd ace bdf aceg bdfh )xor(0 a b ac bd ace bdf aceg

结果如下:

ab abc abcd abcde abcdef abcdefgh abcdefgh


我们已经在最低有效位中累积了原始字中的所有位,XOR’d。 因此,当且仅当输入字中存在偶数个1位(偶校验)时,该位现在为零。 相同的过程适用于32位整数(但需要我们在本演示中跳过的那两个额外的移位)。

最后一行代码简单地删除除了最不重要的位( & 1 )之外的所有位,然后翻转它( ~x )。 如果输入字的奇偶校验是偶数,则结果为1,否则为零。

下面的答案是直接从Bit Twiddling Hacks中解脱出来的Sean Eron Anderson,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日把它寄给了我。

在GCC上有一个内置函数 :

内置函数: int __builtin_parity (unsigned int x)

返回x的奇偶校验,即x modulo 2中的1位数。

即此函数的行为类似于has_odd_parity 。 反转has_even_parity的值。

这保证是GCC上最快的选择。 当然它的使用不是那么便携,但你可以在你的实现中使用它,例如由宏保护。

主要的想法是这个。 使用x & ( x - 1 )取消设置最右边的’1’位。 假设x = 13(1101)并且x & ( x - 1 )1101 & 1100 ,即1100,注意最右边的设置位被转换为0

现在x1100x & ( x - 1 )1100 & 10111000 。 注意原始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); } 

这是一个相当古老的问题,但是我将这个问题发布给将来可能会使用它的人。

我不会在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快得多,它还利用了cpusfunction。

这个例子的作用是将参数作为输入(在RCX中传递 – __fastcall调用约定)。 它将其递增0,从而设置cpus奇偶校验标志,然后如果奇偶校验标志打开则将变量(RAX)设置为0或1。