2012-10-26 3 views
10

Als ich den Quellcode von Java Version 1.7.0_09 gelesen habe, fand ich, dass die Realisierung der toString-Methode der Integer-Klasse verwendet negative int, um die Mod zu berechnen Operation, hat das einen Sinn? Code ist wie folgt:Warum Negativ Int für Mod-Operation in ToString-Methode der Integer-Klasse in Java src

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)); 
} 

Antwort

10

Nach dem Algorithmus, benötigen Sie einen Strom von kleinen (< radix) positiven ganzen Zahlen, die die Zeichenpuffer mit Ziffern von rechts füllen nach links. Um dies zu erreichen, müssen Sie am Anfang der Zahl ein Zeichen setzen und dann den absoluten Wert der Zahl ausgeben.

aber vorstellen, wenn die Regel war, dass i in dieser Schleife immer positiv ist:

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

Wenn iInteger.MIN_VALUE sein geschieht, dann -i geschieht auch Integer.MIN_VALUE zu sein. Two's complement Integer-Variablen können exactly one more negative integer than they can store positive integers speichern. Wenn die Invariante jedoch i ist, ist immer der negative absolute Wert, es passt immer in eine int.

Warum nicht einfach Math.abs() oder einen if Block verwenden? Natürlich werden Ganzzahlen in vielen Computerprogrammen sehr häufig in Zeichenfolgen konvertiert, so dass es nützlich ist, toString so schnell wie möglich zu halten. Das Problem ist, dass sowohl Math.abs() als auch if Anweisungen wahrscheinlich kompiliert werden, um Verzweigungsbefehle zu verwenden, wenn sie zu Maschinencode kompiliert werden. Branches neigen dazu, instruction pipelining zu stören; Wenn Sie also auf die Leistung achten, können Sie, wenn möglich, if Anweisungen aus Schleifen entfernen.

HINWEIS: Diese Art der Optimierung ist selten eine gute Idee! Der Leistungszuwachs ist minimal, es sei denn, Ihr Code wird sehr oft aufgerufen (wie dieser Code) oder Sie erstellen eine Bibliothek mit vielen Benutzern und wenigen Lesern/Modifizierern (wie dieser Code) und machen den Code schwieriger zu lesen, zu verstehen und Veränderung. Wenn Sie diese Optimierung vornehmen, beschleunigen die Java-Entwickler Ihren Code möglicherweise ein wenig - aber wenn Sie solche Techniken in Code schreiben, den Sie schreiben, ist Ihr Kollege vielleicht nicht geneigt, Stack Overflow zu fragen, warum Ihr Code so schwer zu verstehen ist. :)

TL; DR: Nur eine begründete Vermutung, aber das ist eine Kombination von Zweiergänzung Mathematik und Code-Optimierung.

+0

Vielen Dank! Ich denke, das ist was ich will! – Judking

Verwandte Themen