BigDecimalを整数に変換する


134

BigDecimalを返すHibernateメソッドがあります。その番号を渡す必要がある別のAPIメソッドがありますが、パラメーターとして整数を受け入れます。両方のメソッドの戻り値の型または変数の型を変更できません。

次に、BigDecimalをIntegerに変換して2番目のメソッドに渡す方法を教えてください。

これから抜け出す方法はありますか?


6
タイトルを訂正しました。これは変換であり、キャスト
ローン侯爵

回答:


209

あなたはmyBigDecimal.intValueExact()(または単にintValue())呼び出し、情報を失うと例外をスローします。これはintを返しますが、オートボクシングがそれを処理します。


1
intValueExact()良いお勧めです。1.5に追加されました
Anon、

intValue()番号が範囲内であることを確信して100%人生に賭けない限り、電話は危険Integerです。
Snekse 2015年

1
これは意味がありますか:「Integer.valueOf(myBigDecimal.intValueExact())」?
OddDev

32

BigDecimalより大きい値が含まれないことを保証できますInteger.MAX_VALUEか?

はいの場合、ここにあなたのコード呼び出しがありますintValue

Integer.valueOf(bdValue.intValue())

はい。私はそれにInteger.MAX_VALUEより大きい値は含まれません推測する
ヴィシャル

2
プリミティブの代わりにオブジェクトを取得する以外にvalueOfを実行する理由はありませんか?
バジル

私はこれが公式の答えであるべきだと思います。制限に言及している、b。オートボクシングを防止します。
ledlogic

22

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()オートボクシングが行うことだからです
  • 上位ビットをドロップしたときに発生するラップアラウンドが非常に具体的に必要でない限り、他のものが狂っているのでBigDecimal、がInteger範囲よりも大きい場合に例外がスローされます。

これらのパラメーターintValueExact()を指定すると、小数部がゼロ以外の場合に望まないときに例外をスローします。一方、intValue()私たちBigDecimalが大きすぎる場合、例外をスローしません。

両方の利点を最大限に活用するには、BigDecimal最初に四捨五入してから変換します。これには、丸めプロセスをより詳細に制御できるという利点もあります。

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

18

まあ、あなたは呼び出すことができますBigDecimal.intValue()

このBigDecimalをintに変換します。この変換は、Java言語仕様で定義されているdoubleからshortへのプリミティブ変換のナローイングに類似しています。このBigDecimalの小数部分は破棄され、結果の「BigInteger」が大きすぎてintに収まらない場合は、低-order 32ビットが返されます。この変換では、このBigDecimal値の全体的な大きさと精度に関する情報が失われ、反対の符号の結果が返される可能性があることに注意してください。

Integer.valueOf(int)十分に新しいバージョンのJavaを使用している場合は、明示的に呼び出すか、自動ボクシングで自動的に実行させることができます。





-4

上記ではうまくいかないことがわかりました。JTableからセル値をプルしていましたが、doubleやintなどにキャストできませんでした。私の解決策:

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

ここで、行0は常に数値です。これがまだスクロールしている人に役立つことを願っています!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.