BigDecimal'i Tamsayıya Dönüştürme


136

Bana bir BigDecimal döndüren Hibernate yöntemim var. Bu sayıyı geçirmem gereken başka bir API yöntemim var, ancak Tamsayı parametre olarak kabul ediyor. Her iki yöntemin dönüş türlerini veya değişken türlerini değiştiremiyorum.

Şimdi BigDecimal'i Tamsayıya nasıl dönüştürebilir ve ikinci yönteme nasıl geçirebilirim?

Bundan bir çıkış yolu var mı?


6
Unvanınızı düzelttim. Bu dönüşümdür, döküm
Marquis of Lorne

Yanıtlar:


210

Ararsınız myBigDecimal.intValueExact()(veya sadece intValue()) ve bilgiyi kaybederseniz bir istisna bile atar. Bu bir int döndürür, ancak otomatik kutulama bununla ilgilenir.


1
intValueExact()iyi bir öneridir; 1.5
Anon

Numaranın menzil intValue()içinde olduğuna dair% 100 emin olmadığınız sürece aramak tehlikelidir Integer.
Snekse

1
Bu mantıklı mı: "Integer.valueOf (myBigDecimal.intValueExact ())"?
OddDev

32

BigDecimalAsla bundan daha büyük bir değer içermeyeceğini garanti edebilir misiniz Integer.MAX_VALUE?

Cevabınız evet ise, işte kodunuz intValue:

Integer.valueOf(bdValue.intValue())

Evet. Sanırım Tamsayı'dan daha büyük bir değer içermeyecek.MAX_VALUE
Vishal

2
İlkel bir doğru yerine bir Nesne elde etmekten başka değerini yapmanın bir nedeni yok mu?
Basil

Bunun resmi cevap olması gerektiğini söyleyebilirim çünkü a. sınırları belirtir, b. otomatik kutulamayı engeller.
ledlogic

22

TL; DR

Evrensel dönüşüm ihtiyaçları için bunlardan birini kullanın

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

muhakeme

Cevap, gereksinimlerin ne olduğuna ve bu soruları nasıl cevapladığınıza bağlıdır.

  • Will BigDecimalpotansiyel sıfır olmayan kesirli kısmı var?
  • Will BigDecimalpotansiyel sığmayan Integeraralık?
  • Sıfır olmayan kesirli parçaların yuvarlatılmış veya kesilmiş olmasını ister misiniz?
  • Sıfır olmayan kesirli parçaların yuvarlatılmasını nasıl istersiniz?

İlk 2 soruya hayır cevabını verdiyseniz, BigDecimal.intValueExact()başkalarının önerdiği gibi kullanabilir ve beklenmedik bir şey olduğunda patlamasına izin verebilirsiniz .

Eğer 2. sorusuna hakkında kesinlikle% 100 emin değilseniz, o zaman intValue()olduğu hep yanlış cevap.

Daha iyi yapmak

Diğer cevaplara göre aşağıdaki varsayımları kullanalım.

  • Hassasiyeti kaybetmekte ve değeri kırpmakta sorunumuz yok çünkü bu, intValueExact()otomatik boks
  • Aralıktan BigDecimaldaha büyük olduğunda bir istisna atılmasını istiyoruz Integerçünkü yüksek sıralı bitleri düşürdüğünüzde meydana gelen sarmaya çok özel bir ihtiyaç duymadığınız sürece başka her şey çılgınca olacaktır.

Bu parametreler göz önüne alındığında, intValueExact()kesirli bölümümüz sıfır değilse, istemediğimizde bir istisna atar. Öte yandan, intValue()bizim BigDecimalçok büyükse, olması gerektiği zaman bir istisna yapmaz .

Her iki dünyanın da en iyisini elde etmek için BigDecimalilkini tamamlayın , sonra dönüştürün. Bu aynı zamanda size yuvarlama işlemi üzerinde daha fazla kontrol sağlama avantajına sahiptir.

Spock Groovy Testi

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()
}

18

Peki, arayabilirsin BigDecimal.intValue():

Bu BigDecimal'ı bir int'e dönüştürür. Bu dönüşüm, Java Dil Spesifikasyonunda tanımlandığı gibi ikiden kısaya daralan bir ilkel dönüşüme benzer: Bu BigDecimal'in herhangi bir kesirli kısmı atılacak ve sonuçta ortaya çıkan "BigInteger" int'e sığamayacak kadar büyükse, yalnızca düşük -order 32 bit döndürülür. Bu dönüşümün, bu BigDecimal değerinin genel büyüklüğü ve kesinliği hakkındaki bilgileri kaybedebileceğini ve zıt işaretli bir sonuç döndürebileceğini unutmayın.

Integer.valueOf(int)Yeterince yeni bir Java sürümü kullanıyorsanız, bunu açıkça arayabilir veya otomatik kutunun sizin için yapmasına izin verebilirsiniz .


9

Aşağıdakiler hile yapmalı:

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



-4

Yukarıdakilerin benim için işe yaramadığını buldum. Bir JTable'dan bir hücre değeri alıyordum ancak double veya int vb. İçin çeviremedim. Çözümüm:

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

burada satır 0 her zaman bir sayı olacaktır. Umarım bu, hala kaydırma yapan herkese yardımcı olur!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.