61

确定 a 是否是数学意义上的整数值的有效方法是什么?BigDecimal

目前我有以下代码:

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

    return ret;
}

...但如果可能的话,希望避免对象创建开销。

以前我使用bd.longValueExact()which 将避免在内部使用其紧凑表示时创建对象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 回答
5

这可以像某人检查双精度数是否为整数一样完成,执行 % 1 == 0。这就是它查找 BigDecimal 值的方式。

public static boolean isIntegerValue(BigDecimal bd){
  return bd.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) == 0;
}
于 2017-08-08T14:39:30.150 回答
4

一种可能性应该是检查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 回答