zoukankan
html css js c++ java
判断32位整数二进制中1的个数的算法
再转 http://blog.chinaunix.net/uid-20480343-id-1941577.html
今天在CU上看到了关于 “判断32位整数二进制中1的个数的算法” 的问题。因为马上就要下班,没有时间再研究了。只好先把论坛中帖子的地址拷贝下来了。学习ing....
http://dev.bibts.com/32-1-t936968.htm
http://www.chinaunix.net/jh/23/795048.html
在下面的英文网址中,对这个问题有详细的介绍:
http://www.everything2.com/index.pl?node=counting%201%20bits
http://www.everything2.com/index.pl?node=counting%201%20bits%20SPOILER
http://www.everything2.com/index.pl?node_id=1181258
刚开始看到这个问题的时候,我就傻乎乎的开始写代码:
unsigned int FindOneInNumber_00(unsigned int x)
{
unsigned int i,j=1;
unsigned int count=0;
for(i=0;i<32;i++)
{
if((x & j) != 0) count++;
j = j<<2;
}
return count;
}
下面是我写的
很明显我的这段代码写的是非常糟糕的。每次传过来一个数字,我总是要进行32次扫描。就这一点就可以说我的代码是典型的垃圾代码,那么别人是不是有简洁一点的代码呢。在上面的三个英文网址中找到了一些东西。
unsigned int FindOneInNumber_01(unsigned int x)
{
unsigned int n;
for(n=0; x; x >>= 1)
if (x & 1) n++;
return n;
}
在英文文档中,原作者给出的第一种方法。看到这样的代码,俺只能说自己太笨,代码写起来太傻。不就是查查一个数字中 1 的个数吗?自己为啥非得要把所有的 位 都扫描呢? 这是一个值得想想的问题。 原作者给出的代码已经是很不错了,不过,在下面接着他又给出了第二种解法,这第二种解法,更是简洁 优雅 。
unsigned int FindOneInNumber_02(unsigned int x)
{
unsigned int n;
for(n=0; x; n++)
x &= x-1;
return n;
}
原作者给出的第二种方法明显的要优于第一种方法。两者的程序中,循环体执行完后,n表示 1 个个数。x的值变为 0 。两者都达到了目的,循环次数也是一样的。但是二者的区别就在于 第二种方法不用 执行条件判断跳转。当数据量的比较大的时候,二者的差距还是蛮大的。
原文作者又给出第三种方法来解决这个问题:
unsigned FindOneInNumber_03(unsigned int x)
{
const unsigned MASK1 = 0x55555555;
const unsigned MASK2 = 0x33333333;
const unsigned MASK4 = 0x0f0f0f0f;
const unsigned MASK8 = 0x00ff00ff;
const unsigned MASK16 = 0x0000ffff;
x = (x&MASK1 ) + (x>>1 &MASK1 );
x = (x&MASK2 ) + (x>>2 &MASK2 );
x = (x&MASK4 ) + (x>>4 &MASK4 );
x = (x&MASK8 ) + (x>>8 &MASK8 );
x = (x&MASK16) + (x>>16&MASK16);
return x;
}
原文作者的一个朋友又给出一种方法,【查表法】,不过,这样要浪费一定的主存。这种方法也是一个很不错的方法,不过,在单片机下开发的时候,就是个问题的了。象我们公司在单片机上开发游戏,所有的能够给 图片、声音、程序的所有ROM空间仅仅 8MB,采用这种方法就是很不明智的一种选择了。
unsigned numbits_lookup_table[256] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
6, 7, 6, 7, 7, 8
};
unsigned FindOneInNumber_04(unsigned int x)
{
unsigned n;
n = numbits_lookup_table[x & 0xff];
n += numbits_lookup_table[x>>8 & 0xff];
n += numbits_lookup_table[x>>16 & 0xff];
n += numbits_lookup_table[x>>24 & 0xff];
return n;
}
【本程序在Dev C++ 4.9.9.2 下编译通过】
查看全文
相关阅读:
Ubuntu20.04更换软件源
使用kubeadm安装k8s1.19版本之系统基础环境配置&k8s集群初始化(二)
k8s如何删除处于terminating状态的ns资源
k8s如何强制删除pod&pv&pvc和ns&namespace方法
C语言中的有符号数和无符号整形数转换
互联网-架构演进
结合redis使token失效
有一种爱叫做放手
js 读取上传的json文件内容
使用spark-md5获取文件的MD5值
原文地址:https://www.cnblogs.com/zhangfeionline/p/5889370.html
最新文章
内存吞金兽(Elasticsearch)的那些事儿 -- 架构&三高保证
内存吞金兽(Elasticsearch)的那些事儿 -- 数据结构及巧妙算法
内存吞金兽(Elasticsearch)的那些事儿 -- 认识一下
达梦数据库 Linux 安装 部署
CSS 动画
Python3+Selenium 做 UI 自动化输出报告报错<_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>
统计代码行数
word删除空行
jmeter性能监控常用插件下载
倒计时 1 天!ECUG Live 智能运维专题线上分享,参与活动预热领取官方周边!
热门文章
iOS-WKWebView 加载HTML字符自适应文字和图片
Python下的notebook的安装与使用
PyCharm中的indexing...,造成加载项目慢的原因
CentOS各版本区别与下载
Django auth
Django Form
LNMP 方式部署 zabbix 5.0
AWS EC2 实例 SSH 无法登录故障
Ubuntu修改时区和设置24小时时间格式
Ubuntu20.04 TLS 开机卡“A start job is running for wait for network to be Configured”的解决方法
Copyright © 2011-2022 走看看