2016-12-21 25 views
2

[add]這不是關於ArrayIndexOutOfBoundsException的問題,純粹是關於提醒計算算法,請不要將它標記爲重複。如何理解導致ArrayIndexOutOfBoundsException的mod計算的數學公式?

電話拋出ArrayIndexOutOfBoundsException異常,這裏是日誌:

java.lang.ArrayIndexOutOfBoundsException:長度= 36; index = 120 java.lang.IntegralToString.convertInt(IntegralToString.java:234)at java.lang.IntegralToString.appendInt(IntegralToString.java:173)at java.lang.StringBuilder.append(StringBuilder.java:139 )在 android.telephony.SignalStrength.toString(SignalStrength.java:1123)在 com.android.internal.telephony.ServiceStateTracker.onSignalStrengthResult(ServiceStateTracker.java:958) 在

該異常發生在

buf [ - cursor] = DIGITS [r];

我的問題是如何理解代碼如

INT Q =(int)的((0x51EB851FL * I)>>> 37);

INT Q =(0xCCCD * I)>>> 19;

[delete]爲什麼不是int q = i/10; int r = i - 10 * q;

[add] why int q =(0xCCCD * i)>>> 19;相當於int q = i/10;

根據上述算法的評論,r是多少,如果他們是正確的話。

下面

是相關的代碼:

private static final char[] TENS = { 
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 
    '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', 
    '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', 
    '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', 
    '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', 
    '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', 
    '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', 
    '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', 
    '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', 
    '9', '9', '9', '9', '9', '9', '9', '9', '9', '9' 
}; 

/** Ones [i] contains the tens digit of the number i, 0 <= i <= 99. */ 
private static final char[] ONES = { 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
}; 
/** 
* The digits for every supported radix. 
*/ 
private static final char[] DIGITS = { 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 
    'u', 'v', 'w', 'x', 'y', 'z' 
}; 

/** 
    * Returns the string representation of i and leaves sb alone if sb is null. 
    * Returns null and appends the string representation of i to sb if sb is non-null. 
    */ 
    private static String convertInt(AbstractStringBuilder sb, int i) { 
     boolean negative = false; 
     String quickResult = null; 
     if (i < 0) { 
      negative = true; 
      i = -i; 
      if (i < 100) { 
       if (i < 0) { 
        // If -n is still negative, n is Integer.MIN_VALUE 
        quickResult = "-2147483648"; 
       } else { 
        quickResult = SMALL_NEGATIVE_VALUES[i]; 
        if (quickResult == null) { 
         SMALL_NEGATIVE_VALUES[i] = quickResult = 
           i < 10 ? stringOf('-', ONES[i]) : stringOf('-', TENS[i], ONES[i]); 
        } 
       } 
      } 
     } else { 
      if (i < 100) { 
       quickResult = SMALL_NONNEGATIVE_VALUES[i]; 
       if (quickResult == null) { 
        SMALL_NONNEGATIVE_VALUES[i] = quickResult = 
          i < 10 ? stringOf(ONES[i]) : stringOf(TENS[i], ONES[i]); 
       } 
      } 
     } 
     if (quickResult != null) { 
      if (sb != null) { 
       sb.append0(quickResult); 
       return null; 
      } 
      return quickResult; 
     } 

     int bufLen = 11; // Max number of chars in result 
     char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen]; 
     int cursor = bufLen; 

     // Calculate digits two-at-a-time till remaining digits fit in 16 bits 
     while (i >= (1 << 16)) { 
      // Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8 
      int q = (int) ((0x51EB851FL * i) >>> 37); 
      int r = i - 100*q; 
      buf[--cursor] = ONES[r]; 
      buf[--cursor] = TENS[r]; 
      i = q; 
     } 

     // Calculate remaining digits one-at-a-time for performance 
     while (i != 0) { 
      // Compute q = n/10 and r = n % 10 as per "Hacker's Delight" 10-8 
      int q = (0xCCCD * i) >>> 19; 
      int r = i - 10*q; 
      buf[--cursor] = DIGITS[r]; 
      i = q; 
     } 

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

     if (sb != null) { 
      sb.append0(buf, cursor, bufLen - cursor); 
      return null; 
     } else { 
      return new String(cursor, bufLen - cursor, buf); 
     } 
    } 
+0

至於你的其他問題:**爲什麼不是int q = i/10; int r = i - 10 * q; **,位移操作通常更快(?)。但編譯器知道它是否應該在位移時進行乘法運算或做其他事情。所以,最好把它放在編譯器的彙編實現上。因此,如果你需要乘法,然後使用乘法,如果你需要分割,然後使用除法,而不是做位移 – rafid059

+0

我真的不知道你的問題。你問爲什麼**你的** mod計算會導致異常?或者你在這裏問兩個**完全獨立的東西?! – GhostCat

+0

我只能理解爲什麼使用這樣的公式「int q =(0xCCCD * i)>>> 19;」它不直觀,很難理解它的功能以及是否正確。 – Saint

回答

1
  1. int q = (int) ((0x51EB851FL * i) >>> 37);

0x在號碼的開頭是指數被寫入十六進制表示

L在數字的結尾意味着數字是Long-type。那就是爲什麼(int)使用。

>>>37意味着該表達式左邊數字的二進制表示應該向右移動37次。例如:

16 >>> 2 
16 in binary is 10000. 
shift it to the right 2 times, we got 100.00 
100 in decimal system is equal to 4. 
16 >>> 2 = 4. 
  • 同約int q = (0xCCCD * i) >>> 19;

  • 爲什麼不int q = i/10; int r = i - 10q;

  • IMO移HEXADEMICAL號碼是更比劃分更快,更精確。

    1. 根據以上關於算法的評論,r是多少,如果他們是正確的話。

    我敢肯定,你可以簡單地在你的IDE中調試它,以獲得答案。

    +0

    1.我不能明白爲什麼它們是等價的這個int Q =(0xCCCD * I)>>> 19;和int q = i/10; 2.這個問題目前還不能複製的,我已經寫了一個演示,該算法,提醒少10始終。所以我很困惑。 – Saint