Java 如何将 int 类型的数字转换为二进制、十六进制。
最编程
2024-05-22 19:38:54
...
以前一直没有关注过int型数字是怎么转换成二进制,十六进制的呢?虽然以前面试的时候也被问到过,却一直不知道Java内部是怎么实现的。所以今天就看了下Integer的静态方法toHexString(int i), toOctalString(int i), toBinaryString(int i)等方法是怎么实现的。发现都会调用如下这个方法进行统一处理:
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
//Integer.numberOfLeadingZeros(val)用来计算最高位前有多少个零
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);
//将数组字符变成String返回
return new String(buf);
}
为了方便理解这个转换过程,我将会用17这个数字说明这整个过程,17对应的二进制为:00000000 00000000 0000000 00010001。首先我们来看下Integer.numberOfLeadingZeros(int val)这个方法是怎么计算最高位前面有多少个零的吧。
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
int n = 1;
//首先将值无符号右移16位,17右移16位后:0000000 00000000 00000000 00000000
//由此可知这个if条件是满足的,执行if里面的代码后 n=17 由于将i进行了有符号左移,所以现在的i
//为:0000000 00010001 00000000 00000000
if (i >>> 16 == 0) { n += 16; i <<= 16; }
//将新的值无符号右移24位,右移24位后:00000000 00000000 00000000 00000000
//由此可知这个if条件满足,执行if里面的代码后 n=25 i有符号左移后
//为:00010001 00000000 00000000 0000000
if (i >>> 24 == 0) { n += 8; i <<= 8; }
//将新的值无符号右移28位,右移28未后:00000000 00000000 00000000 0000001
//该if条件不满足
if (i >>> 28 == 0) { n += 4; i <<= 4; }
//将新的值无符号右移30位,右移30未后:00000000 00000000 00000000 0000000
//由此可知这个if条件满足,执行if里面的代码后 n=27 i有符号左移后
//为:01000100 00000000 00000000 0000000
if (i >>> 30 == 0) { n += 2; i <<= 2; }
//下面这个相当判断最高位是不是1,如果是1,则减1。只有负数最高位才是1。
n -= i >>> 31;
//最后这里返回的n=27
return n;
}
Integer.numberOfLeadingZeros(int val)就分析完了,就是通过不断的移位运算来判断最高位前面有多少个零,看到这里的时候,我有个疑问,负数还有必要调用这个方法吗,因为最高位永远都是1,这个方法返回的总是0。不知道这样想是否有问题。
接下来我们就来看下这个formatUnsignedInt()方法是怎么将int型转成相应的数字格式的吧。
/**
* @param val 需要转换的数字
* @param shift 将基数的log2转换为以下格式(4表示十六进制,3表示八进制,1表示二进制)
* @param buf 数组用来存转换后的结果
* @param offset 数组起始位的偏移量
* @param len 数组的长度
*/
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;
//标示不同数字格式下所能表达的最大数,比如十六进制15,八进制7
//这里拿转换成八进制为例: mask = 7(二进制表示为111)
int mask = radix - 1;
do {
//将值与mask进行&运算,并从Integer.digits数组中找到对应的字符,Integer.digits存储的是字符'0'-'9'和'a'-'z'
//八进制为例,这里就是拿最低三位与mask&运算
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}
关于Java是怎么进行进制的就解析完了,有问题欢迎一起讨论学习。
上一篇: 二进制、八进制和十六进制