Integer类toString(int i, int radix)方法的解析

博客围绕Java中Integer类的toString(int i, int radix)方法展开,作者查看该方法源码时,发现将正数转为负数再进行进制转换的设计很巧妙。经分析,这是为避免边界值-2^31转为正数超出int范围,导致无法获得正确结果,还涉及补码知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前项目需要使用到进制转换,然后找到了Integer类提供的方法toString(int i, int radix),查看使用时顺便看了下源码。发现源码有的地方写的很巧妙。现在趁有空记录一下

先看一下源码:

        public static String toString(int i, int radix) {
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* 如果是10进制,直接转字符串即可 */
        if (radix == 10) {
            return toString(i);
        }

        // 存放转换进制后的字符数组
        char buf[] = new char[33];
        boolean negative = (i < 0);
        // 将指针指向buf数组最后一位,以便后边存放字符
        int charPos = 32;

        if (!negative) {
            i = -i;
        }

        /* 使用短除法来转换进制 */
        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];

        if (negative) {
            buf[--charPos] = '-';
        }

        return new String(buf, charPos, (33 - charPos));
    }

其实上边使用的短除法,基本大家在数学都学过,如果忘了可以网上搜一下。

if (!negative) {
      i = -i;
}

但是在这里为何把正数转为负数,再进行进制转换呢。网上查了一下别人的回答,使用正数也能得到相同的结果。难道这是多此一举?后来经过思考,其实并不是的。先来推导一下过程,假如将18转成2进制,即i=18,radix=2:

(1)将转为负数: i = -18;

(2)反复使用短除法:

        buf : ...............0  ,  i : -9

        buf : .............10  ,  i : -4

        buf : ...........010  ,  i : -2

        buf : .........0010  ,  i : -1

        buf : .......10010 

(3)如果negative为true,那么进制数前还要加个‘-’。

这里结果为10010。

假设我们按正数的方法进行,获得结果是相同的。如此看来,为何还要先转负数再转换呢,其实我们少考虑一种情况,边界值。int的范围是-2^31——2^31-1。当值为-2^31时,如果将其转为正数再进行进制转换,那么变为2^31已超出int的范围,其实java执行结果还是-2^31,还是负数。那么在while循环的i <= radix条件则不成立,无法获得正确的结果。

为何i = -2^31时,执行i = -i,i仍等于-2^31。

-2^31的补码为 1000 0000 0000 0000 0000 0000 0000 0000,当将其转为正数时,对应补码理解就是-x=~x+1,即补码取反加1。那么获得结果还是 1000 0000 0000 0000 0000 0000 0000 0000。

个人的理解大概是这样,欢迎大家来看,有什么不对地方请指点出来。突然感觉基础还是挺重要的,不知不觉就用到了大学学的计算机原理。

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值