Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why using negative int for mod operation in toString method of Integer class in java src

when I read the source code of java version 1.7.0_09, I found that the realization of toString method of Integer class uses negative int to calculate the mod operation, is there any sense to that? code is as follows:

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));
}
like image 776
Judking Avatar asked Oct 26 '12 04:10

Judking


1 Answers

According to the algorithm, you need a stream of small (< radix) nonnegative integers that will fill the character buffer with digits from right to left. The standard, primary-school way to make this work is to put a sign at the beginning of the number, and then print the absolute value of the number.

But imagine if the rule were that i is always positive in that loop:

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

If i happens to be Integer.MIN_VALUE, then -i also happens to be Integer.MIN_VALUE. Two's complement integer variables can store exactly one more negative integer than they can store positive integers. However, if the invariant is instead that i is always the negative absolute value, it will always fit in an int.

Why not just use Math.abs() or an if block? Naturally, integers are converted to strings very frequently in many computer programs, so it is useful to keep toString as fast as possible. The trouble is, both Math.abs() and if statements will likely be compiled to use branch instructions when compiled to machine code. Branches tend to interfere with instruction pipelining; therefore, when paying attention to performance you might choose to remove if statements from loops when possible.

NOTE: This kind of optimization is rarely a good idea! The performance gain is miniscule unless your code is called very very frequently (like this code) or you are building a library with lots of users and few readers/modifiers (like this code), and it makes code harder to read, understand, and change. By making this optimization, the Java engineers might speed up your code very slightly--but if you put techniques like this in code you write, your coworker/grader may not be inclined to ask Stack Overflow why your code is so hard to understand. :)

TL;DR: Just an educated guess, but this is a combination of two's complement math and code optimization.

like image 183
Jeff Bowman Avatar answered Oct 01 '22 18:10

Jeff Bowman