您的位置 首页 java

JAVA源码之Integer-2

  • bitCount
public static int bitCount(int i);返回int的 二进制 数中1的数量,源码如下: 

这个方法很有意思,解法如下:

简单的描述这个方法的逻辑就是,

第一步:每2位一组,分组算出1的个数

第二步:每4位一组,分组算出1的个数

第三步:每8位一组,分组算出1的个数

第四步:每16位一组,分组算出1的个数

第五步:全部(32位)一起算出1的个数

第六步:去掉无用位,返回结果

最后一步:

举例详解:

先看下0x55555555、0x33333333、0x0f0f0f0f对应的二进制

0x55555555 = 01010101010101010101010101010101
0x33333333 = 00110011001100110011001100110011
0x0f0f0f0f = 00001111000011110000111100001111
0x3f = 00000000 00000000 00000000 00111111 

举例一个数i的二进制为:00110101 10110001 00010001 00001111

第一步:每2位一组,分组算出1的个数

首先i>>>1 = 00011010 11011000 10001000 10000111 
//二进制右移动一位,高位补0
然后((i >>> 1) & 0x55555555) = 00010000 01010000 00000000 00000101
//计算出原i的奇数为上1的个数(结果为0或1)
最后i - ((i >>> 1) & 0x55555555) = 00100101 01100001 00010001 00001010
//计算出每两位上的i的个数(从左到右,2位一组,结果位0(00)或1(01)或2(10)) 

第二步:每4位一组,分组算出1的个数 (以第一步的结果来计算)

首先i & 0x33333333 = 00100001 00100001 00010001 00000010 
//对第一步结果 每四位一组,计算出每四位的后两位的1的个数
其次 i >>> 2 = 00001001 01011000 01000100 01000010
//第一步的结果右移两位
然后 ((i >>> 2) & 0x33333333) = 00000001 00010000 00000000 00000010
//对第一步结果 每四位一组,计算出每四位的前两位的1的个数
最后 (i & 0x33333333) + ((i >>> 2) & 0x33333333) = 
00100010 00110001 00010001 00000100
//每四位一组,计算出每四位里1的个数 

第三步:每8位一组,分组算出1的个数(以第二步的结果来计算)

首先i >>> 4 = 00000010 00100011 00010001 00010000 
//对第二步结果 右移4位 
其次(i + (i >>> 4)) & 0x0f0f0f0f 可以分解为 i & 0x0f0f0f0f + (i >>> 4) & 0x0f0f0f0f
//对第二步结果 每八为一组 分别计算出每八位的前四位和后四位的1的个数,然后相加得出每八位的1的个数
i & 0x0f0f0f0f = 00000010 00000001 00000001 00000100 //每八位后四位1的个数
(i >>> 4) & 0x0f0f0f0f = 00000010 00000011 00000001 00000000 // 每八位前四位的1个数
i & 0x0f0f0f0f + (i >>> 4) & 0x0f0f0f0f =
 00000100 00000100 00000010 00000100 
//每八位1的个数,这里可以注意到每八位1的数量都用后四位表示出来了 

第四步:每16位一组,分组算出1的个数(以第三步的结果来计算)

首先 i >>> 8 = 00000000 00000100 00000100 00000010 
//第三步的结果右移8位
然后 i + (i >>> 8) = 00000100 00001000 00000110 00000110
//这里我们可以注意到每16位的后8位其实就是这16位1的个数,前8位无用,后面会消去 

第五步:全部(32位)一起算出1的个数(以第四步的结果来计算)

首先 i >>> 16 = 00000000 00000000 00000100 00001000
//对第四步结果右移16位
其次 i + (i >>> 16) = 00000100 00001000 00001010 00001110
//这里我们注意到是把第四步结果的第一个16位和第2个16位的后八位相加,
//得到所有的1的个数,前面24位其实都无用 

第六步:去掉无用位,返回结果

i & 0x3f = 00000000 00000000 00000000 00001110 

所以最后二 进制 00110101 10110001 00010001 00001111的1的个数为:14

总结:取二进制里1的个数方法有很多,但这里实现的很奇妙,思路很奇特,不愧是大师们的杰作

  • decode

把String字符解码成Integer数字,0x和#开头处理成16进制,0开头处理成8进制,其它为10进制

  • toUnsigned long :返回无符号long类型转换的数值
  • divideUnsigned:返回 无符号整数 整除的商
  • remainderUnsigned:返回无符号整数整除的余数
  • formatUnsignedInt:将数字转换为字符数据存放在字符buf中
  • getInteger:
public static Integer getInteger(String nm) 
public static Integer getInteger(String nm, int val) 
public static Integer getInteger(String nm, Integer val)
最后用System.getProperty()和Integer.decode()实现 
  • lowestOneBit
public static int lowestOneBit(int i);返回对应二进制最低位为1的位置 
  • highestOneBit
public static int highestOneBit(int i);返回最高位为1的位置 
  • max、min:利用Math的max和min函数取较大和较小的数字
  • rotateLeft、rotateRight循环左移(将移出高的位放到该数的低位)、右移(将移出的低位放到该数的高位)

文章来源:智云一二三科技

文章标题:JAVA源码之Integer-2

文章地址:https://www.zhihuclub.com/198998.shtml

关于作者: 智云科技

热门文章

网站地图