61

aが数学的な意味で整数値かどうかを判断する効率的な方法は何ですか?BigDecimal

現在、次のコードがあります。

private boolean isIntegerValue(BigDecimal bd) {
    boolean ret;
    
    try {
        bd.toBigIntegerExact();
        ret = true;
    } catch (ArithmeticException ex) {
        ret = false;
    }

    return ret;
}

...しかし、可能であればオブジェクト作成のオーバーヘッドを避けたいです。

以前は、 がコンパクトな表現を内部で使用してbd.longValueExact()いる場合にオブジェクトの作成を回避するために使用していBigDecimalましたが、値が大きすぎて long に収まらない場合は明らかに失敗していました。

4

7 に答える 7

94

編集: Java 8 の時点で、stripTrailingZeroes() はゼロを占めるようになりました

BigDecimal stripTrailingZeros がゼロに対して機能しない

そう

private boolean isIntegerValue(BigDecimal bd) {
  return bd.stripTrailingZeros().scale() <= 0;
}

今はまったく問題ありません。


scale()いくつかの回答に記載されている解決策を使用する場合は、stripTrailingZeros()ゼロに注意する必要があります。ゼロは、スケールに関係なく常に整数stripTrailingZeros()であり、ゼロ BigDecimal のスケールを変更しません。

したがって、次のようなことができます。

private boolean isIntegerValue(BigDecimal bd) {
  return bd.signum() == 0 || bd.scale() <= 0 || bd.stripTrailingZeros().scale() <= 0;
}
于 2012-10-05T14:21:09.250 に答える
18

値のソース/使用法によっては、BigDecimal最初にスケール <= 0 かどうかを確認する方が速い場合があります。そうであれば、それは間違いなく数学的な意味での整数値です。>0 の場合は、整数値のままである可​​能性があり、よりコストのかかるテストが必要になります

于 2009-07-03T11:34:53.497 に答える
8

数値を 1 で割り、剰余を調べます。整数を 1 で割ったときの剰余は常に 0 でなければなりません。

public boolean isWholeNumber(BigDecimal number) {
    return number.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) == 0;
}
于 2015-03-27T22:57:26.647 に答える
6

これを使用できます(他の回答から要約するだけです):

private boolean isIntegerValue(BigDecimal bd) {
  return bd.stripTrailingZeros().scale() <= 0;
}
于 2010-06-06T18:30:15.417 に答える
4

1 つの可能性は、 scale()がゼロまたは負かどうかを確認することです。その場合、 BigDecimal の小数点以下の数字はなく、質問を正しく理解していれば、数値は数学的な整数でなければなりません。

更新: 正の場合でも整数である可能性がありますが、その場合、さらに詳細なチェックのために追加のオブジェクトの作成を惜しむことはできません。このような場合の例は、stripTrailingZeros()メソッドの javadoc に示されています (Joachim の回答のヒントに感謝します)。

于 2009-07-03T11:38:22.240 に答える
1

これは私が思いついた中で最もきれいです。

public static boolean isWhole(BigDecimal bigDecimal) {
    return bigDecimal.setScale(0, RoundingMode.HALF_UP).compareTo(bigDecimal) == 0;
}
于 2014-10-31T10:35:17.060 に答える