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 下编译通过】
查看全文
相关阅读:
方差分析
Rust 指定安装目录
perl 子函数传入多个数组
perl 获取目录信息
R绘图布局包 customLayout
C语言 自定义函数按行读入文件2
C语言 自定义函数按行读入文件
C语言按行读入文件
sed删除指定行
mybatis 批量更新
原文地址:https://www.cnblogs.com/zhangfeionline/p/5889370.html
最新文章
exe4j将java项目打包成exe程序
iview upload组件的运用
Swing表格数据转xls文档
vue 参数的简单AES加密
Windows7(x64) 安装Python3.7.0
最长回文字串算法,Manacher
Vert.x(vertx) 简明介绍
简单3步快速生成千万级别mysql测试数据库,模拟电商数据
超卖问题
如何对博客进行备份和还原?(适用于博客园)
热门文章
PostgreSQL:Java使用CopyManager实现客户端文件COPY导入
java操作excel在开始位置添加一列
网站
无法加载文件 vue.ps1 系统禁止运行脚本
VSCode搭建Vue项目
使用淘宝镜像cnpm安装Vue.js的图文教程
vue安装之后找不到vue.cmd文件
Node.js安装及环境配置之Windows篇
rust Option枚举
rust shadow
Copyright © 2011-2022 走看看