经验,制造一切未来,经验,是所有过去的成果。而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
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
-
CODE-2
int chars = Math.max(((mag + (shift - 1)) / shift), 1); (mag + (shift - 1))/shift
即mag / shift
向上取整。 (证明参照我另外一篇博客 【java面试题-算法】除法如何向上取整? 比如8进制shift为3,2进制有10位bit,chars就是10/3向上取整4 ) 。
-
CODE-3
char[] buf = new char[chars];
-
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);val & mask
表示就是val转为目标进制低位的值, digits是个存了[0-z]共36个字符的数组,下标0对应’0’,1对应’1’,15对应’F’。于是以
val & mask
为下标取得digit字符为val的目标进制的低位字符。val >>>= shift
相当于value=value>>>shift
。从低到高,每获取一位,将位置再往右边移shift (代表待转进制中一位需要的二进制位数) 。 逐字节判断。然后将结果放入buf中。比如val为10进制的9,其二进制表达式为1001,mask为111,digit[1001& 111] = digit[1] = '1'。然后1001 >>>= 3 = 1。 最后执行digit[1&111] = digt[1] = '1'。所以9的八进制表达式为11。