如果偶数为1位,则值具有偶校验。如果具有奇数1位,则该值具有奇校验。例如,0110
具有偶校验,1110
具有奇校验。
如果1
具有偶数奇偶校验,我必须返回x
。
int has_even_parity(unsigned int x) {
return
}
答案 0 :(得分:54)
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return (~x) & 1;
假设你知道整数是32位。
让我们看看它是如何工作的。为了简单起见,让我们使用一个8位整数,我们可以跳过前两个移位/异或。让我们通过 h 标记 a 位。如果我们查看我们的号码,我们会看到:
( a b c d e f g h )
第一个操作是x ^= x >> 4
(记住我们正在跳过前两个操作,因为在这个例子中我们只处理一个8位整数)。让我们通过组合XOR一起的字母来写入每个位的新值(例如, ab 表示该位具有值 a xor b < / i>的)。
( 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 b ac bd ace bdf aceg )
结果如下:
( a ab abc abcd abcde abcdef abcdefgh abcdefgh )
我们已经在最低有效位中累积了原始字中的所有位,XOR'd。因此,当且仅当输入字中存在偶数个1位(偶校验)时,该位现在为零。相同的过程适用于32位整数(但需要我们在本演示中跳过的那两个额外的移位)。
最后一行代码只删除除最不重要位(& 1
)之外的所有位,然后翻转它(~x
)。如果输入字的奇偶校验是偶数,则结果为1,否则为零。
答案 1 :(得分:5)
直接从Bit Twiddling Hacks By 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日寄给我。
答案 2 :(得分:3)
尝试:
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;
}
瓦尔特
答案 3 :(得分:2)
在GCC上有一个built-in function:
内置函数:
int __builtin_parity (unsigned int x)
返回
x
的奇偶校验,即x modulo 2中的1位数。
即。此函数的行为类似于has_odd_parity
。反转has_even_parity
。
这保证是GCC上最快的选择。当然它的使用不是那么便携,但你可以在你的实现中使用它,例如由宏保护。
答案 4 :(得分:1)
主要思想是这个。取消最右边的&#39; 1&#39;使用x & ( x - 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
次操作之后,NSString *dateFormat = @"dd/MM/yyyy HH:mm:ss a";
NSTimeZone *inputTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
NSDateFormatter *inputDateFormatter = [[NSDateFormatter alloc] init];
[inputDateFormatter setTimeZone:inputTimeZone];
[inputDateFormatter setDateFormat:dateFormat];
**NSDate *date = [inputDateFormatter dateFromString:_strLiveStreamStartTime];**
NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone];
NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init];
[outputDateFormatter setTimeZone:outputTimeZone];
[outputDateFormatter setDateFormat:dateFormat];
NSString *outputString = [outputDateFormatter stringFromDate:date];
NSLog(@"%@",outputString);
变为零,则其为奇校验,否则为偶校验。
答案 5 :(得分:1)
概括@ 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);
}
答案 6 :(得分:0)
int parity_check(unsigned x) {
int parity = 0;
while(x != 0) {
parity ^= x;
x >>= 1;
}
return (parity & 0x1);
}
答案 7 :(得分:0)
这是一行#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)可以获得相同的效率。假设您保留一行定义。
答案 8 :(得分:-3)
这是一个相当古老的问题,但是我将这个问题发布给将来可能会使用它的人。
我不会在c中添加一个例子,因为已经有足够好的答案了。
如果最终结果应该是一段可以用c程序工作(编译)的代码,那么我建议如下:
.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快得多,它还利用了cpus功能。
这个例子的作用是将参数作为输入(在RCX中传递 - __fastcall调用约定)。它将其递增0,从而设置cpus奇偶校验标志,然后如果奇偶校验标志打开则将变量(RAX)设置为0或1。