经验,制造一切未来,经验,是所有过去的成果。而jdk源码是优秀的经验。
Integer.toBinaryString用于打印整形Integer的二进制字符串,类似还有toOctalString打印八进制字符串,toHexString打印十六进制。与基于10进制转向二进制,八进制,十六进制的过程 (将10进制的数字除以二,每次除得的余数保存起来,一直除到最后商小于1,代码结尾进行拼接再输出) 不同。JDK用更加直观简洁的方法快速求得。
以Integer.toBinaryString为例,其调用toUnsignedString0(int val, int shift),val为待转的整数,shift是进制数各位的权值用bit表示所需要的bit数量 (2进制shift=1,8进制shift=3,16进制shift=4)。其流程是首先确定字符串长度,然后确定字符串每个位置的值。
toUnsignedString0里面有2个方法,numberOfLeadingZeros确定整数补码数字高位为0的数量。formatUnsignedInt确定每个位置的字符。
源码
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}
private static String toUnsignedString0(int val, int shift) {
/* 分析 code-1 */
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
/* 分析 code-2 */
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
/* 分析 code-3 */
char[] buf = new char[chars];
/* 把计算好的字符推如buf中 */
formatUnsignedInt(val, shift, buf, 0, chars);
/* 返回结果String */
return new String(buf, true);
}
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
/* len就是字符串长度 */
int charPos = len;
/* 分析 code-4 */
int radix = 1 << shift;
int mask = radix - 1;
/* 分析 code-5 */
do {
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}
分析
- CODE-1
|
- 计算机里面所有数据都以二进制(补码)的形式存在,这里就是获取val在计算机内的二进制码长度,numberOfLeadingZeros表示高位全为0的个数, Integer.SIZE为32,代表Integer在java里面的4字节32位。mag就是除去高位全0的二进制位数。
- CODE-2
|
-
这里就是计算val待转为的进制的位数,也就是结果字符串的长度。shift代表待转进制中一位需要的二进制位数。
(mag + (shift - 1))/shift
即mag / shift
向上取整。 - CODE-3
|
- 初始化结果字符串buf。java中的字符串其实是一个char数组,java内置的编码方式是unicode的UTF-16。
- CODE-4
|
- 1往左移shift位实际上得到的是待转为进制各位权值的二进制表达。二进制权值为2 (shift=1 用10表示) , 八进制权值为8 (shift=3 用1000表示 ),十六进制权值为16 (shift=4 用10000表示) ,分别将其减1得到mask,即目标进制各位的最大数字,二进制为1 (1),八进制为7 (111),16进制为15 (1111)。
- CODE-5
|
-
mask为目标进制各位的最大数字,
val & mask
表示就是val转为目标进制低位的值, digits是个存了[0-z]共36个字符的数组,下标0对应’0’,1对应’1’,15对应’F’。
于是以val & mask
为下标取得digit字符为val的目标进制的低位字符。 val >>>= shift
相当于value=value>>>shift
。从低到高,每获取一位,将位置再往右边移shift (代表待转进制中一位需要的二进制位数) 。 逐字节判断。然后将结果放入buf中。
|