[英]Can doubles or BigDecimal overflow?
Java 8給了我們Math.addExact()的整數但不是小數。
double
和BigDecimal
有可能溢出嗎? 通過Double.MAX_VALUE和如何獲得最大的BigDecimal值判斷我會說答案是肯定的。
因此,為什么我們不為這些類型使用Math.addExact()
? 什么是最可維護的方式來檢查這個?
double
溢出到Infinity
和-Infinity
,它不會環繞。 BigDecimal
不會溢出,期間,它僅受計算機內存量的限制。 請參閱: 如何獲得最大的BigDecimal值
+
和.addExact
之間的唯一區別是它嘗試檢測是否發生了溢出並拋出異常而不是換行。 這是源代碼:
public static int addExact(int x, int y) {
int r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
如果要檢查溢出已經發生了,在某種意義上,這是簡單的做它用double
無論如何,因為你可以簡單地檢查Double.POSITIVE_INFINITY
或Double.NEGATIVE_INFINITY
; 在int
和long
的情況下,這是一個稍微復雜的問題,因為它並不總是一個固定值,但在另一個中,這些可能是輸入(例如Infinity + 10 = Infinity
,你可能不想拋出異常在這種情況下)。
由於所有這些原因(我們甚至還沒有提到NaN
),這可能是JDK中不存在這樣的addExact
方法的原因。 當然,您始終可以將自己的實現添加到自己的應用程序中的實用程序類中。
你不需要一個浮點數的addExact
函數的原因是因為它不是環繞,而是溢出到Double.Infinity
。
因此,您可以在操作結束時非常輕松地檢查它是否溢出。 由於Double.POSITIVE_INFINITY + Double.NEGATIVE_INFINITY
是NaN,因此如果表達式更復雜,還必須檢查NaN。
這不僅更快,而且更容易閱讀。 不要讓Math.addExact(Math.addExact(x, y), z)
一起添加3個雙打,而是可以寫:
double result = x + y + z;
if (Double.isInfinite(result) || Double.isNan(result)) throw ArithmeticException("overflow");
BigDecimal
,另一方面確實會溢出,並扔在這種情況下,一個相應的異常,以及-這是不太可能永遠在實踐中發生,但。
如需double
,請查看其他答案。
BigDecimal
有addExact()
保護已經內置了許多運算方法(如multiply
)的BigDecimal
包含對結果的規模進行檢查:
private int checkScale(long val) {
int asInt = (int)val;
if (asInt != val) {
asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
BigInteger b;
if (intCompact != 0 &&
((b = intVal) == null || b.signum() != 0))
throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
}
return asInt;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.