Java源码解读之常量52429

发布于:2024-06-27 ⋅ 阅读:(13) ⋅ 点赞:(0)


在JDK8源码中 java.lang.Integer有52429作为常量出现,

为什么有52429的常量呢?

static void getChars(int i, int index, char[] buf) {
    int q, r;
    int charPos = index;
    char sign = 0;

    if (i < 0) {
        sign = '-';
        i = -i;
    }

    // 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); //相当于i/10;
        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;
    }
}

public static String toString(int i) {
    if (i == Integer.MIN_VALUE)
        return "-2147483648";
    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
    char[] buf = new char[size];
    getChars(i, size, buf);
    return new String(buf, true);
}

固定的形式是一个整型变量乘上52429,然后向右移19位。很自然想到2^19=524288,那么这个52429就不难理解了,应该就是除10的操作。

除法是很慢的,而乘法和以为却相对较快,所以为了优化这一点点的速度,java采用了乘52429再移19位的方法。

对于为什么选择52429?

这里列出几个取值的精度:

 103/1024≈0.1006 (2^10)
 205/2048≈0.100098 (2^11)
 ……
 26215/262144≈0.100002 (2^18)
 52429/524288≈0.10000038 (2^19)
 104858/1048576≈0.10000038 (2^20)

可见,到2^19次方左右,除10的精度已经非常高了。

那么为什么不再选几位呢?

原因很简单:

  • java中整型占32位,而52429的二进制是1100110011001101(16位),65535的二进制是111111111111111(16位),相乘结果为31位。
  • 通过阅读上述源码的这个方法可知,i是不会大于65535的(注释中也提到:assert(i <= 65536, i);),所以算上符号位,能达到精度最大而又不溢出的也就是2^19了。