如何检查值是偶数奇偶校验还是奇数?
如果偶数为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位整数,我们可以跳过前两个移位/异或。 让我们标记位a到h 。 如果我们查看我们的号码,我们会看到:
( 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
。
现在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); }
这是一个相当古老的问题,但是我将这个问题发布给将来可能会使用它的人。
我不会在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。