// I use the "invariant division by multiplication" trick to // accelerate Integer.toString. In particular we want to // avoid division by 10. // // The "trick" has roughly the same performance characteristics // as the "classic" Integer.toString code on a non-JIT VM. // The trick avoids .rem and .div calls but has a longer code // path and is thus dominated by dispatch overhead. In the // JIT case the dispatch overhead doesn't exist and the // "trick" is considerably faster than the classic code. // // TODO-FIXME: convert (x * 52429) into the equiv shift-add // sequence. // // RE: Division by Invariant Integers using Multiplication // T Gralund, P Montgomery // ACM PLDI 1994
我们知道计算机在计算除法效率要比加减乘法低。所以为了避免除法,提高计算效率,采用此种方法。
正好我们可以看看Long的toString方法里的stringSize方法。
1 2 3 4 5 6 7 8 9 10
// Requires positive x staticintstringSize(long x){ long p = 10; for (int i=1; i<19; i++) { if (x < p) return i; p = 10*p; } return19; }
publicstaticintparseInt(String s, int radix) throws NumberFormatException { /* * WARNING: This method may be invoked early during VM initialization * before IntegerCache is initialized. Care must be taken to not use * the valueOf method. */
if (s == null) { thrownew NumberFormatException("null"); }
if (radix < Character.MIN_RADIX) { thrownew NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); }
if (radix > Character.MAX_RADIX) { thrownew NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); }
int result = 0; boolean negative = false; int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; int multmin; int digit;
if (len > 0) { char firstChar = s.charAt(0); if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Integer.MIN_VALUE; } elseif (firstChar != '+') throw NumberFormatException.forInputString(s);
if (len == 1) // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); i++; } multmin = limit / radix; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++),radix); if (digit < 0) { throw NumberFormatException.forInputString(s); } if (result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; if (result < limit + digit) { throw NumberFormatException.forInputString(s); } result -= digit; } } else { throw NumberFormatException.forInputString(s); } return negative ? result : -result; }
static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h;
cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; }