如何找到偶数或奇数的“1”位

时间:2017-12-31 01:01:59

标签: c binary parity

是否可以通过单次测试说明C中int的二进制表示中是偶数还是奇数“1”位?如果没有最快的方法呢?

5 个答案:

答案 0 :(得分:1)

解决此问题的一种方法是计算位数并检查最低有效位以查看该值是奇数还是分别是eval1 。给定一个32位整数,我们可以通过一些巧妙的位操作来计算其二进制表示Hamming Weight0的数量。已经找到汉明重量here的答案很好,而且它也谈到了效率问题。

采用这种算法通过横向累积加法找到汉明重量。如果1的奇数为hasOddCount,则1会返回x

1

答案 1 :(得分:1)

也许不是最快的,但它的工作原理非常简单:

int evenNumberOfOnes(unsigned int num)
{
    int n=0;
    while(num > 0) {
        n ^= num;
        num = num >> 1;
    }
    return n & 1;
}

感谢@EricPostpischil提供有关改进的提示。

答案 2 :(得分:0)

我确信这不是最不可能的代码,但它简短易懂;

#include <stdio.h>

int main(int argc, const char * argv[]) {
    unsigned x;
    int count;

    scanf("%u\n",&x);

    for(count=0;x;x>>=1)
        if(x&1)
            ++count;

    puts(count&1?"odd":"even");

    return(0);
}
顺便说一下:我正在编写血液酒精含量为.05的代码,我没有检查过,如果我把这个简单的任务搞错了,明天我可能会感到尴尬。请不要将此代码放入任何使用热核武器或无人驾驶汽车的地方。

编辑:看到其他答案后也可能是正确的&amp; |棘手的;最快的代码真的取决于架构。模数在某些CPU上速度非常快,而在其他CPU上则会占用很多周期。一切都确实在大约相同的几个周期内发生变化。

答案 3 :(得分:0)

int parity(int n) {
   int p = 0;

   for (;n;n>>=1) {
      p = (n&1) ? 1-p : p;
   }

   return p;
}
如果参数n中的1的数量是偶数,则

将返回零。简单测试:

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

int main() {
   srand(time(NULL));
   for (int i=0;i<100;i++) {   
      int n = rand();
      printf("%d has an %s number of 1's \n", n, parity(n)  ? "odd" : "even");
   }
}

答案 4 :(得分:0)

我发布这个作为一个新的答案,因为它有点hackish和我的其他答案有点不同。

int evenNumberOfOnesFast(unsigned int num)
{
    unsigned char *b;
    b = (unsigned char *)&num;
    unsigned char par[4]={0};

    for(int i=0; i<8; i++) {
        for( int j=0; j<4; j++) {
            par[j]^=b[j];
            b[j]=b[j] >> 1;
        }
    }
    return (par[0] ^ par[1] ^ par[2] ^ par[3]) & 1;
}

这里,我假设int是4个字节。我希望这能使cpu在管道中并行完成一些工作。我不确定是不是这样,但这比我以前的版本快两倍。

以下是测试它的主要功能:

#define N 10000000
int main()
{
    int * arr = malloc(N*sizeof(*arr));
    int * par = malloc(N*sizeof(*par));

    // Random values to prevent optimizer from just removing the code                                              
    srand(time(NULL));

    for(int i=0; i<N; i++)
        arr[i]=rand();

    // Correctness check                                                                                           
    for(int i=0; i<N; i++)
        if(evenNumberOfOnes(arr[i]) != evenNumberOfOnesFast(arr[i])) {
            perror ("Error");
            exit(EXIT_FAILURE);
        }

    clock_t begin, end;
    double time_spent;

    begin = clock();

    for(int i=0; i<N; i++)
        par[i]=evenNumberOfOnes(arr[i]);

    end = clock();
    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf(" Time: %f\n", time_spent);

    begin = clock();

    for(int i=0; i<N; i++)
        par[i]=evenNumberOfOnesFast(arr[i]);

    end = clock();
    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf(" Time: %f\n", time_spent);
}

结果:

$ cc r.c -O3 -Wall -Wextra
$ ./a.out 
 Time: 0.201635
 Time: 0.093152

但是,我还测试了@ Miket25提供的解决方案hasOddCount,它实际上比我的快速变体快十倍。