JDK:Integer.getChars(inti,intindex,char[]buf

在Integer类的源码中,toString方法中调用getChars方法,getChars方法是获取数值对应的字符串,其中有两个地方使用了非常巧妙的方式来进行除法运算和取余运算。在计算机中,a/b 和 a%b相比较位运算,都是比较费时的计算的。下面来看看jdk中是如何优化计算的

成都创新互联专注为客户提供全方位的互联网综合服务,包含不限于网站设计、成都网站建设、禹州网络推广、重庆小程序开发、禹州网络营销、禹州企业策划、禹州品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联为所有大学生创业者提供禹州建站搭建服务,24小时服务热线:028-86922220,官方网址:www.cdcxhl.com

// Generate two digits per iteration
while (i >= 65536) {
        q = i / 100;
// really: r = i - (q * 100);
        r = i - ((q << 6) + (q << 5) + (q << 2));
        i = q;
        buf [--charPos] = DigitOnes[r];
        buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
        q = (i * 52429) >>> (16+3);
        r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
        buf [--charPos] = digits [r];
        i = q;
        if (i == 0) break;
}
if (sign != 0) {
        buf [--charPos] = sign;
}

思路是这样:
当 i >= 65536时,是每两位取出数字,i /= 100,例如 i = 567235474,
(1)先取最后两位 7 和 4 放入buf数组中,i = 5672354,buf = { , , , , , , , '7', '4'};
(2)再取最后两位 5 和 4 放入buf数组中,i = 56723,buf = { , , , , , '5', '4', '7', '4'};
当 i < 65536 时,跳出循环,采用每一次取出一位数字,也就是 i /= 10
(3)取最后一位 3 放入buf数组中,i = 5672,buf = { , , , , '3', '5', '4', '7', '4'};
(4)取最后一位 2 放入buf数组中,i = 567,buf = { , , , '2', '3', '5', '4', '7', '4'};
(5)取最后一位 7 放入buf数组中,i = 56,buf = { , , '7', '2', '3', '5', '4', '7', '4'};
(6)取最后一位 6 放入buf数组中,i = 5,buf = { , '6', '7', '2', '3', '5', '4', '7', '4'};
(7)取最后一位 5 放入buf数组中,i = 0,buf = { '5', '6', '7', '2', '3', '5', '4', '7', '4'},结束。
但在jdk中,并不都是直接用 a/b 除法 和 a%c 取余来获取 商 和 余数的

1、对100除法:q = i / 100,直接除法

2、对100取余:r = i - ((q << 6) + (q << 5) + (q << 2));
推导如下:
       r = i - (q x 100)
       r = i - (q x 64 + q x 32 + q x 4)
       r = i - ((q << 6) + (q << 5) + (q << 2))

3、对10除法:q = (i x 52429) >>> (16+3);
推导如下:
2 >>> 19 为 524288,
q = (52429 x i) / 524288 = (52428.8 x i + 0.2 x i) >>> (16+3),
i 拆分为两部分,i = a x 10 + b(保证a, b 均为正数,且 0 <= b <= 9,
q = ((10a + b) x 52428.8 + 0.2b) >>> 19
q = (524288a + 52428.8b + 0.2i) >>> 19
其中,
52428.8b 最大值为52428.8 x 9, 0.2i 最大值为 13107.2
所以,
52428.8b + 0.2i 最大值为 484966.4, 小于 524288 (1 >>> 19), 对应二进制会被右移掉
所以,
q = (a x 524288) >>> 19 + (52428.8 x b + i * 0.2) >>>19 = (a x 524288) >>> 524288 = a

4、对10取余:r = i - ((q << 3) + (q << 1));
推导如下:
       r = i - (q x 10)
       r = i - (q x 8 + q * 2)
       r = i - ((q << 3 + q << 1)

从这个方法我们学到的

1、乘法比除法高效:q = ( i 52429) >>> (16+3); => 约等于q0.1,但i52429是整数乘法器,结合位移避免除法
2、充分利用计算结果:在获取r(i%100)时,充分利用了除法的结果,结合位移避免重复计算
3、位移比乘法高效:r = i – (( q << 6) + ( q << 5) + ( q << 2)); = >等价于r = i – (q
100)
4、局部性原理之空间局部性


网站名称:JDK:Integer.getChars(inti,intindex,char[]buf
文章来源:http://ybzwz.com/article/jjpcpg.html