免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: ciedecem
打印 上一主题 下一主题

求一个整数的bit位中1的个数 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-07-06 06:44 |只看该作者
回复 5# 塑料袋

分治这种方法最好只在面试的时候用来 sm 考官,自己用的时候还是老老实实地地查表吧
   

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
12 [报告]
发表于 2012-07-06 09:13 |只看该作者
回复 10# blackuhlan


   

这个。。。
我咋感觉你这是单片机上的程序呢?

论坛徽章:
4
天秤座
日期:2015-01-09 16:08:43狮子座
日期:2015-01-10 12:54:442015年亚洲杯之卡塔尔
日期:2015-01-29 23:02:232015亚冠之卡尔希纳萨夫
日期:2015-10-17 10:41:11
13 [报告]
发表于 2012-07-06 12:51 |只看该作者
本帖最后由 sleepcat 于 2012-07-06 12:54 编辑

http://www.myfavor.org/program/2011-10-03/359.html

一个无符号数,写一个函数将其2进制的位数为1的个数返回出来。
#include<stdio.h>
int main()
{
    int x=0xF1A0;
    int i=0;
    while(x)
    {
        x &= x-1;
        ++i;
    }
    printf("count=%d\n", i);
    return 0;
}
其实,最关键的部分就是“x &= x -1; ”
说明:不管二进制是什么,减1就会从右到左把0变为1,直至碰见1,把1变为0才结束.
如果x=x&(x-1), 就是把从左到右连续的0都变为1,并且遇到的第一个1变为0!
举例:10010100000  减1  就是:10010011111  ,再“&”就等于 10010000000  (红色部分)
这样循环一次,就是把最右边的1变为零。
有多少个1,就循环多少次。直到最后x的值变为0

论坛徽章:
0
14 [报告]
发表于 2012-07-06 15:59 |只看该作者
1、11楼说的对,直接查表法是最快的。可以参考<编程之美>
2、10楼的需要N多判断的case会转化为一堆的if语句。
3、3楼的算法需要更高的条件,要求知道,并且通过数学验证的,算法效率还远不及查表算法快。
4、要求是最快的。

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
15 [报告]
发表于 2012-07-07 20:26 |只看该作者
本帖最后由 captivated 于 2012-07-07 20:54 编辑

回复 5# 塑料袋


    不错. 这段代码非常快, 效率高而且简洁. 很hack, 如你所讲, 这就是求unsigned int中bit位为1的个数的标准算法.(第一次发成unsigned long了. 对于64位构架上采用LP模型的编译器, unsigned long是64位, unsigned int还是32位. 嗯, 这种算法的唯一缺陷就是要求整数的位数固定, 稍微欠缺了点移植性.) 我大约是在一年前, 一个驱动工程师发上来这段代码求解释时才第一次见到这种做法. 什么查表法就是浮云.


论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
16 [报告]
发表于 2012-07-07 21:19 |只看该作者
本帖最后由 starwing83 于 2012-07-07 21:20 编辑

int hweight32(unsigned int w) {
    const char *p = "\0\1\1\2\1\2\2\3";
    int count = 0;
    while (w) {
        count += p[w&0x7];
        w >>= 3;
    }
    return count;
}

这样不是更简单么= =

论坛徽章:
4
戌狗
日期:2013-08-15 18:22:43技术图书徽章
日期:2013-08-21 13:48:45巨蟹座
日期:2013-09-26 17:06:39处女座
日期:2013-12-25 11:26:10
17 [报告]
发表于 2012-07-07 22:42 |只看该作者
starwing83 发表于 2012-07-07 21:19
int hweight32(unsigned int w) {
    const char *p = "\0\1\1\2\1\2\2\3";
    int count = 0;


32bit还看不出来什么

但我那个实际上是递归的办法,64bit上就要比循环查表NB了

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
18 [报告]
发表于 2012-07-08 00:05 |只看该作者
http://hi.baidu.com/sunyubo458/b ... 9b7a7f3812bb7a.html

找到一篇文章……

话说,64bit也就查个20多次的样子吧……如果用16位表(“\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4")的话,也就查个16次啊……不过你得处理五遍,每次两个(或三个)位操作一个加法,一共是20次位操作加加法,也没快多少呗……

好吧……其实的确是那个比较牛逼,就是看到《C专家编程》里面的一句话(是这本书吧= =貌似不是这本),我也忘了哪儿说的了,说这个算法仅仅具有理论上的优势,其实查表更好一点(难道是《代码之美》么……)

最后,这么斤斤计较似乎有点过了,这年头编译器很牛逼的(参见那个gcc优化bswap的文,理论上我的方案比楼主的慢很多——位操作多得多,但实际上是一样的,因为编译器猜到了你要干嘛,直接优化成bswap了)。

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
19 [报告]
发表于 2012-07-08 05:53 |只看该作者
回复 18# starwing83


    谁评估一下两个程序的运行性能?不就更有说服力么?

论坛徽章:
0
20 [报告]
发表于 2012-07-08 12:53 |只看该作者
最快就是直接用数字电路逻辑门,不可能还有比这更快的了。逻辑电路应该很简单。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP