算法之统计一个8bit中1的个数

来源:互联网 发布:大数据要什么学历 编辑:程序博客网 时间:2024/06/03 19:07

统计一个8bit中1的个数

写了那么多天java语言的知识,基本已经算是比较全面了。今天翻了手边的几本java语言类书,没有找到可以写的东西。所以今天就抓了一本编程之美来研究一哈。


对于这个问题我一开始的想法就是做一个遍历。把byte类型toString()然后比较字符就好了。后来一想这是基本类型,并不继承于object。

第一种方法

package test;public class Main {static byte b =9;public static void main(String[] args) {System.out.println(count(b));}private static int count(byte b) {int sum = 0;while (b != 0) {if (b % 2 == 1) {System.out.print(1);sum++;} elseSystem.out.print(0);b /= 2;}System.out.println();return sum;}}

顺便学习了一下如何把一个数变成二进制。或者是n进制。


看到了上面这个算法的乘除运算,而且运算数是2的倍数,那么很自然就想到位运算了,这是计算机最擅长的运算方式。

于是改进之:

将b/=2 改成b >>= 1;

将上面的if判断也改成sum+=b&1;

当b的最后一位是1的时候和1做与运算,只有是1的时候sum才自增1.然后右移一位。

基于以上的操作算法已经优化到一定程序了。

不过仍然是有多少位就需要执行多少次遍历。

不知道作者是怎么想出下面的这个方法的。

private static int count(byte b) {int sum = 0;while (b != 0) {b&=(b-1);sum++;}System.out.println();return sum;}

的确是正确的。以8为例,1001&(1000)=1000&(0110)=0;

如果 是10呢。1011&(1010)=1010&(1001)=1000&(0110)=0;

每一个等于号都是sum自增1.

还有比这效率更高的么。。有的。。有一种算法叫做查表法。。以空间换取时间。因为是8bit。所以最大是256.我们只需要列一个数组将每个数有几个1都放在数组,到时直接根据数字就能得到数组里这个数字位的1的个数了。

比如 [256]={0,1,1,2,1,2,2.......};



书后有一个课后题。这本书是不给答案的,我就试着写一下了。

说是如果 变量变成32位的Dword,会使用哪一个算法。

当然用那个类似于递归的与运算算法了。

用查表的话代价太大。

改进后如下


private static int count(DWORD b) {int sum = 0;int temp = b.intValue();while (temp != 0) {temp &= (temp - 1);sum++;}System.out.println();return sum;}

第二题,给定两个整数,A和B,问把A变成B需要改变多少位。

还是根据与运算的那个算法得到启发,用异或运算可以算出,相同的位结果为1,不同为0.然后我们再统计多少个1就可以了。

package test;import com.sun.jna.platform.win32.WinDef.DWORD;public class Main {static DWORD d = new DWORD(2342342);static DWORD d1 = new DWORD(2342341);public static void main(String[] args) {count(d);count(d1);System.out.println(count(d, d1));}private static int count(DWORD b) {int sum = 0;int temp = b.intValue();while (temp != 0) {if (temp % 2 == 1) {System.out.print(1);sum++;} elseSystem.out.print(0);temp /= 2;}System.out.println();return sum;}private static int count(DWORD b, DWORD b1) {int sum = 0;int temp = (b.intValue() ^ b1.intValue());count(new DWORD(temp));while (temp != 0) {temp &= (temp - 1);sum++;}System.out.println();return sum;}}
输出结果:

0110001110111101110001
1010001110111101110001
11

2

另外注意不要将用dword中的bytevalue方法,有人因为例子中是这个类型就被迷惑了。bytevalue方法返回的是byte类型。而这个类型只能表示0到255.32位的dword转换后会丢失数据。









0 0