誰かがBigDecimal
が数学的な意味で整数値であるかどうかを判断するefficient方法を推奨できますか?
現在、私は次のコードを持っています:
_private boolean isIntegerValue(BigDecimal bd) {
boolean ret;
try {
bd.toBigIntegerExact();
ret = true;
} catch (ArithmeticException ex) {
ret = false;
}
return ret;
}
_
...しかし、必要に応じてオブジェクト作成のオーバーヘッドを回避したい。以前はbd.longValueExact()
を使用していましたが、BigDecimal
が内部でコンパクトな表現を使用している場合はオブジェクトの作成を回避しましたが、値が長すぎて長さに収まらない場合は明らかに失敗しました。
助けてくれてありがとう。
BigDecimal
値のソース/使用法によっては、スケール<= 0かどうかを最初に確認する方が速い場合があります。もしそうなら、それは間違いなく数学的な意味での整数値です。それが> 0の場合、それはcouldでも整数値であり、より高価なテストが必要になります。
編集: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;
}
_
数値を1で割り、余りを確認します。 1で割ったとき、整数は常に0の余りを持つ必要があります。
public boolean isWholeNumber(BigDecimal number) {
return number.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) == 0;
}
あなたはこれを使うことができます(他の答えから要約するだけです):
private boolean isIntegerValue(BigDecimal bd) {
return bd.stripTrailingZeros().scale() <= 0;
}
scale() がゼロまたは負であるかどうかを確認することが1つの可能性です。その場合、BigDecimalの小数点以下の桁数はなく、質問が正しく理解されていれば、数値は数学的な整数である必要があります。
Update:正の場合、それはまだ整数である可能性がありますが、その場合、詳細なチェックのために余分なオブジェクトの作成を惜しむことはできません。そのような場合の例は、 stripTrailingZeros() メソッドjavadocで提供されています(Joachimの回答のヒントをありがとう)。
これは私が思いついた中で最もきれいです。
public static boolean isWhole(BigDecimal bigDecimal) {
return bigDecimal.setScale(0, RoundingMode.HALF_UP).compareTo(bigDecimal) == 0;
}
これは、誰かがdoubleが整数かどうかをチェックするのと同じ方法で実行でき、%1 == 0を実行します。これは、BigDecimal値を探す方法です。
public static boolean isIntegerValue(BigDecimal bd){
return bd.remainder(new BigDecimal("1")).compareTo(BigDecimal.ZERO) == 0;
}