为什么在java src中的Integer类的toString方法中使用负int进行mod操作

Jud*_*ing 10 java tostring modulo

当我读到java版本1.7.0_09的源代码时,我发现Integer类的toString方法的实现使用了负int来计算mod操作,有什么意义吗?代码如下:

public static String toString(int i, int radix) {

    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10;

    /* Use the faster version */
    if (radix == 10) {
        return toString(i);
    }

    char buf[] = new char[33];
    boolean negative = (i < 0);
    int charPos = 32;

    if (!negative) {     
        i = -i;                //***** change i to negative
    }

    while (i <= -radix) {
        buf[charPos--] = digits[-(i % radix)];   //***** change back to positive after 
                                                 //***** mod operation
        i = i / radix;
    }
    buf[charPos] = digits[-i];

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

    return new String(buf, charPos, (33 - charPos));
}
Run Code Online (Sandbox Code Playgroud)

Jef*_*ica 10

根据该算法,您需要一个small(< radix)非负整数流,它将从右到左填充字符缓冲区.使这项工作的标准小学方法是在数字的开头加上一个符号,然后打印数字的绝对值.

但想象一下,如果规则i在那个循环中始终是正面的:

if (negative) {
    i = -i; // change i to positive
}
Run Code Online (Sandbox Code Playgroud)

如果i恰好是Integer.MIN_VALUE,那么-i也恰好是Integer.MIN_VALUE.二进制补码整数变量可以存储一个比它们可以存储正整数更多的负整数.但是,如果不变量i总是绝对值,它将始终适合于int.

为什么不使用Math.abs()if阻止?当然,在许多计算机程序中,整数会非常频繁地转换为字符串,因此toString尽可能快地保持整数是有用的.问题是,编译成机器代码时,两者Math.abs()if语句都可能被编译为使用分支指令.分支往往会干扰指令流水线 ; 因此,在注意性能时,您可以选择if在可能的情况下从循环中删除语句.

注意:这种优化很少是个好主意!除非你的代码被非常频繁地调用(比如这段代码),或者你正在构建一个包含大量用户和少量读者/修饰符(如此代码)的库,并且它使代码更难以阅读,理解,并且性能增益微乎其微.更改.通过进行这种优化,Java工程师可能会非常轻微地加速您的代码 - 但是如果您将这样的技术放在您编写的代码中,您的同事/评级员可能不会倾向于询问Stack Overflow为什么您的代码很难理解.:)

TL; DR:只是一个有根据的猜测,但这是两个补码数学和代码优化的组合.