欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

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是怎么进行进制的就解析完了,有问题欢迎一起讨论学习。