2017-02-20 80 views
3

我已經經歷了Apache的普通數學庫Link溢出檢測減去2個多頭

在下面的代碼片段線A,B時,C沒有道理給我。有人可以對此有所瞭解嗎?

public static long subAndCheck(long a, long b) throws MathArithmeticException { 
     long ret; 
     if (b == Long.MIN_VALUE) { ----------A 
      if (a < 0) { --------------------B 
       ret = a - b; ----------------C 
      } else { 
       throw new MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, -b); 
      } 
     } else { 
      // use additive inverse 
      ret = addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION); 
     } 
     return ret; 
    } 

private static long addAndCheck(long a, long b, Localizable pattern) throws MathArithmeticException { 
     final long result = a + b; 
     if (!((a^b) < 0 || (a^result) >= 0)) { 
      throw new MathArithmeticException(pattern, a, b); 
     } 
     return result; 
    } 
+1

檢查此問題http://stackoverflow.com/questions/3001836/how-does-java-handle-integer-underflows-and-overflows-and-how-would-you-check-fo#3001879 –

回答

3

所以,Long.MIN_VALUE == -(Long.MAX_VALUE + 1) == -Long.MAX_VALUE - 1,特別Long.MIN_VALUE == -Long.MIN_VALUE。所以如果a >= 0,加/減Long.MIN_VALUE將始終產生溢出。這意味着這是一種特殊情況,該方法必須測試(A),並且僅在a < 0(B)時才執行實際減法。由於我們已經測試過可能的溢出,我們可以簡單地做(C)。

+0

正是我在找的東西!!!!! – KodeWarrior

1

將最小可能的數字MIN_VALUE進行抽取與添加最大數字MAX_VALUE相同。實際上,它甚至是MAX_VALUE+1,因爲在java中,long都是有符號的,而且0編碼像正數,所以正數少於負數。

這就是爲什麼a必須小於0的這個減法(加法)工作(B)。但是,如果a小於0且b是可能的最小數字。 a - b一定會成功。 (C)

爲什麼這個特例甚至被檢查(A)的原因是因爲這種情況,小數可能數的絕對值比最大可能數大1,因此行addAndCheck(a, -b, LocalizedFormats.OVERFLOW_IN_ADDITION);會失敗在該位置-b