最快的判断32位整数二进制中1的个数的算法

算法一:

const int one_in_char[256]=
{
    0, 1, 1, 2, 1, 2,2,3
......
                              ,8
}
//此为 0-255 每个数中 1 的个数。
//这个雕虫小技在密码,crc...等地方使用很广泛。
int func2(int v)
{
    int n=v;
    unsigned char *ptr=(unsigned char *)&n;
    return one_in_char[ptr[0]]+one_in_char[ptr[1]]+one_in_char[ptr[2]]+one_in_char[ptr[3]];
}


算法二:

unsigned int func(unsigned int x)
{
    x = (x & 0x55555555UL) + ((x >> 1) & 0x55555555UL); // 0-2 in 2 bits
    x = (x & 0x33333333UL) + ((x >> 2) & 0x33333333UL); // 0-4 in 4 bits
#if 1
    // Version 1
    x = (x & 0x0f0f0f0fUL) + ((x >> 4) & 0x0f0f0f0fUL); // 0-8 in 8 bits
    x = (x & 0x00ff00ffUL) + ((x >> 8) & 0x00ff00ffUL); // 0-16 in 16 bits
    x = (x & 0x0000ffffUL) + ((x >> 16) & 0x0000ffffUL); // 0-31 in 32 bits
    return x;
#else
    // Version 2
    x = (x + (x >> 4)) & 0x0f0f0f0fUL; // 0-8 in 4 bits
    x += x >> 8; // 0-16 in 8 bits
    x += x >> 16; // 0-32 in 8 bits
    return x & 0xff;
#endif
}


对比测试代码:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

int count=0x7FFFFFFF;

unsigned int func(unsigned int x)
{
    x = (x & 0x55555555UL) + ((x >> 1) & 0x55555555UL); // 0-2 in 2 bits
    x = (x & 0x33333333UL) + ((x >> 2) & 0x33333333UL); // 0-4 in 4 bits
#if 1
    // Version 1
    x = (x & 0x0f0f0f0fUL) + ((x >> 4) & 0x0f0f0f0fUL); // 0-8 in 8 bits
    x = (x & 0x00ff00ffUL) + ((x >> 8) & 0x00ff00ffUL); // 0-16 in 16 bits
    x = (x & 0x0000ffffUL) + ((x >> 16) & 0x0000ffffUL); // 0-31 in 32 bits
    return x;
#else
    // Version 2
    x = (x + (x >> 4)) & 0x0f0f0f0fUL; // 0-8 in 4 bits
    x += x >> 8; // 0-16 in 8 bits
    x += x >> 16; // 0-32 in 8 bits
    return x & 0xff;
#endif
}

int one_in_char[256];
int func2(int *v)
{
    unsigned char *ptr=(unsigned char *)v;
    return one_in_char[ptr[0]]+one_in_char[ptr[1]]+one_in_char[ptr[2]]+one_in_char[ptr[3]];
}

void test_1()
{
  int t1, t2;
  int i, v;
   char v2=0;
  t1 = time(NULL);
  for (i=0; i<count; i++)
    {
      v = func(i);
       v2+=v; /* 若不加这个,v 没使用,循环被优化掉了 */
    }
  t2 = time(NULL);
  printf("time of func: %d   v2=%d\n", t2-t1, v2);
}

void test_2()
{
  int t1, t2;
  int i, v;
   char v2=0;
  for (i=0; i<256; i++)
    one_in_char[i]=i%8;  /* 这 256 为硬编码, 为简便起见,随便设,不影响计算时间 */
  t1 = time(NULL);
  for (i=0; i<count; i++)
    {
      v = func2(&i);
       v2+=v; /* 若不加这个,v 没使用,循环被优化掉了 */
    }
  t2 = time(NULL);
  printf("time of func2: %d   v2=%d\n", t2-t1, v2);
}

int main(int argc, char **argv)
{
  test_1();
  test_2();
  return 0;
}


来源

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值