十进制转换二进制toBinaryString源码分析
// 十进制转换二进制toBinaryString源码分析
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}
代码的主要流程是分为两步:
第一步,使用toUnsignedString0方法计算出用于表示二/八/十六进制的字符数组的长度;
第二步,使用formatUnsignedInt方法填充字符数组,得到所需进制表示的字符串并返回。
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
char[] buf = new char[chars];
formatUnsignedInt(val, shift, buf, 0, chars);
// Use special constructor which takes over "buf".
return new String(buf, true);
}
//1.计算最高位0的个数;众所周知在jvm中一个int类型的数据占4个字节,共32位;
//从左边第一位开始数0的个数一直到第一个不是0的位置(遇到第一个1终止计数)
//首先判断下0的情况(即32位都是0),直接返回32即可;
//然后我们将分别从高16位和低16位中查找第一个不为0的位置(第一个1)
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
int n = 1;
// 将i无符号(补0)向右偏移16位,看i是否等于0,如果为0说明刚刚的偏移量(高16位)中都是0;则i至少有16位都是0;
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
// 判断第一个非零值是否位于左边第一位
// 在方法的开始已经判断并返回了变量为0即所有的位均为0的情况,
// 所以能进行到后面的代码部分,说明变量不为0,即必然存在至少一个位为1,
// 判断到这里,高两位中必然有一个为1,所以判断高一位即可知晓连续0的个数;
n -= i >>> 31;
return n;
}
// 可以通过 ASCII码进行int和char的转化
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}