2010-10-28 190 views
102

我有Hibernate方法,它返回給我一個BigDecimal。 我有另一個API方法,我需要通過該號碼,但它接受Integer作爲參數。我無法更改這兩種方法的返回類型或變量類型。將BigDecimal轉換爲整數

現在如何將BigDecimal轉換爲Integer並將其傳遞給第二個方法?

有沒有辦法呢?

+4

我更正了你的標題。這是*轉換,*不*鑄造。* – EJP 2010-10-29 00:32:17

回答

162

你會打電話myBigDecimal.intValueExact()(或只是intValue()),它甚至會拋出一個異常,如果你會失去信息。這返回一個整數,但自動裝箱處理。

+1

'intValueExact()'是一個很好的建議;它被添加到1.5中 – Anon 2010-10-28 14:08:52

+0

調用'intValue()'是危險的,除非你100%打賭你的生活,它肯定該數字在整數範圍內。 – Snekse 2015-03-14 20:53:37

+1

這是否合理:「In​​teger.valueOf(myBigDecimal.intValueExact())」? – OddDev 2015-10-01 05:38:00

29

您能否保證BigDecimal永遠不會包含大於Integer.MAX_VALUE的值?

如果是的話,那麼這裏是你的代碼中調用intValue

Integer.valueOf(bdValue.intValue()) 
+0

是的。我猜它不會包含比Integer更大的值.MAX_VALUE – Vishal 2010-10-28 14:04:01

+1

除了獲取對象而不是原始權利之外,沒有理由執行valueOf? – Basil 2014-07-18 22:08:50

+0

我會說這應該是官方答案,因爲a。提到了限制,b。防止自動裝箱。 – ledlogic 2015-06-26 21:31:03

5

之後應該做的伎倆:

BigDecimal d = new BigDecimal(10); 
int i = d.intValue(); 
13

嗯,你可以撥打BigDecimal.intValue()

將此BigDecimal轉換爲int。這種轉換類似於Java語言規範中定義的縮小的從雙精度到小精度的原始轉換:此BigDecimal的任何小數部分都將被丟棄,並且如果生成的「BigInteger」太大而無法放入int,則只有低返回32位。請注意,此轉換可能會丟失有關此BigDecimal值的總體幅度和精度的信息,並會返回相反符號的結果。

然後,您可以顯式調用Integer.valueOf(int)或讓自動裝箱爲你做,如果您使用的是足夠新的Java版本。

14

TL; DR

使用這些通用轉換一個需要

//Java 7 or below 
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact() 
//Java 8  
bigDecimal.toBigInteger().intValueExact() 

推理

的答案取決於需求是什麼,以及如何回答這些問題。

  • BigDecimal可能有一個非零小數部分?
  • BigDecimal可能不適合Integer範圍?
  • 要非零小數部分圓整還是截斷?
  • 您認爲非零小數部分圓整嗎?

如果您對前2個問題回答「否」,您可以像其他人所建議的那樣使用BigDecimal.intValueExact(),並在意外發生時讓它爆炸。

如果你對問題2號不是絕對100%的信心,那麼intValue()總是錯誤的答案。

使之更好

讓我們使用基於其他的答案如下假設。

  • 我們都還可以與丟失精度和截斷值,因爲這就是intValueExact()和自動裝箱做
  • 我們希望拋出一個異常時,該BigDecimalInteger範圍更大,是因爲別的更是瘋狂,除非你有一個非常具體的需要,當你放棄高位時發生。

鑑於這些參數,intValueExact()拋出一個例外,當我們不希望它,如果我們的小數部分是非零。另一方面,如果我們的BigDecimal太大,intValue()不會拋出異常。

爲了獲得兩全其美的效果,先將BigDecimal四捨五入,然後轉換。這也有利於您更多地控制舍入過程。

斯波克Groovy的測試

void 'test BigDecimal rounding'() { 
    given: 
    BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99) 
    BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99) 
    BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000") 
    String decimalAsBigIntString = decimal.toBigInteger().toString() 
    String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString() 
    String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString() 

    expect: 'decimals that can be truncated within Integer range to do so without exception' 
    //GOOD: Truncates without exception 
    '' + decimal.intValue() == decimalAsBigIntString 
    //BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information 
    // decimal.intValueExact() == decimalAsBigIntString 
    //GOOD: Truncates without exception 
    '' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString 

    and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception' 
    //BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648 
    //'' + hugeDecimal.intValue() == hugeDecimalAsBigIntString 
    //BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information 
    //'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString 
    //GOOD: Throws conversionOverflow ArithmeticException because to large 
    //'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString 

    and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception' 
    //BAD: hugeDecimal.intValue() is 0 
    //'' + reallyHuge.intValue() == reallyHugeAsBigIntString 
    //GOOD: Throws conversionOverflow ArithmeticException because to large 
    //'' + reallyHuge.intValueExact() == reallyHugeAsBigIntString 
    //GOOD: Throws conversionOverflow ArithmeticException because to large 
    //'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString 

    and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal' 
    //decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact() 
} 
-2

我發現上面並沒有爲我工作。我拉着從JTable中單元格的值,但不能轉換爲加倍或INT等我的解決辦法:

Object obj = getTable().getValueAt(row, 0); 

其中row 0將始終是一個數字。希望這可以幫助任何人仍然滾動!