如何使用带有两个Number实例的modulo?

时间:2017-04-03 19:28:52

标签: java numbers modulo

我遇到了一个场景,其中我有两个 Number 实例,我需要检查一个是否是另一个的倍数。

我尝试使用modulo来检查例如:




  public static boolean isMultipleOf(Number a,Number b){
返回%b == 0;
}
  




但编译器不喜欢它:

& #xA;




运算符'%'无法应用于'java.lang.Number',
 'java.lang.Number'







我明白为什么会这样,但我的问题是什么是最简单的实现方式这个?

实际值可以是任何类型的数字,我想避免检查每个数字的实际数字类型,然后才执行操作。

&# xA;


任何想法?

谢谢!




3 个答案:

答案 0 :(得分:1)

你可以这样做:

public static boolean isMultipleOf(Number a, Number b) {
    return a.longValue() % b.longValue() == 0;
}

当然,这假设ab是数学上的整数(如此短整数,整数或长整数)。您可以使用doubleValue()代替,但要注意浮点代数比较...

答案 1 :(得分:1)

您可以使用doubleValue方法将参数转换为double并应用%,例如:

private static boolean isMultipleOf(Number a, Number b){
    return (a.doubleValue() % b.doubleValue()) == 0.0;
}

它也适用于intfloat,例如:

public static void main(String[] args) throws Exception{
    System.out.println(isMultipleOf(20, 10));
    System.out.println(isMultipleOf(20.0, 10));
    System.out.println(isMultipleOf(20, 10.0));
    System.out.println(isMultipleOf(20.0, 10.0));
}

以上打印true 4次。

<强>更新

如果您处理大量数字,那么您可以使用BigDecimal类'remainder方法,例如:

private static boolean isMultipleOf(Number a, Number b){
    return new BigDecimal(a.doubleValue()).remainder(new BigDecimal(b.doubleValue())).doubleValue() == 0.0;
}

答案 2 :(得分:1)

如果没有类型检查

,你就不能这样做

A Number仅提供转换为基元的方法,而每个基元都不足以给出准确的答案。

doubleValue不起作用

static boolean wrongIsMultipleOfUsingDouble(Number a, Number b) {
    return (a.doubleValue() % b.doubleValue()) == 0;
}

由于double只有53位的精度,当输入为需要63位精度的long时,它会给出错误的答案:

System.out.println(wrongIsMultipleOfUsingDouble(6969696969696969696L, 3L));
// prints `false`, but should be `true`
System.out.println(wrongIsMultipleOfUsingDouble(7777777777777777777L, 2L));
// prints `true`, but should be `false`.

longValue不起作用

static boolean wrongIsMultipleOfUsingLong(Number a, Number b) {
    return (a.longValue() % b.longValue()) == 0;
}

显然,由于截断,它不起作用。

System.out.println(wrongIsMultipleOfUsingLong(5.0, 2.5));
// prints `false`, but should be `true`     
System.out.println(wrongIsMultipleOfUsingLong(4.5, 2.0));
// prints `true`, but should be `false`.

类型检查仅适用于已知类型。

尽管OP喜欢避免类型检查,但这确实是接近可接受解决方案的唯一方法。

static boolean wrongIsMultipleOfUsingTypeChecking(Number a, Number b) {
    // pseudo-code for simplicity
    if (a, b instanceof (AtomicInteger | AtomicLong | Byte | Integer | Long | ...)) {
        return (a.longValue() % b.longValue()) == 0;
    } else if (a, b instanceof (Double | DoubleAccumulator | DoubleAdder | Float) {
        return (a.doubleValue() % b.doubleValue()) == 0;
    } else if (a, b instanceof (BigInteger | BigDecimal)) {
        return a.remainder(b) == ZERO;
    } else {
        throw new RuntimeError("I give up");
    }
}

这在大多数情况下都没问题,但它仍然无效,因为它无法处理Number的第三方子类,比如org.apache.commons.math4.fraction.Fraction

仅限于JSON号码?

现在OP声明使用了Number因为数字来自JSON。这些数字通常只有longdouble,因此类型检查方法就足够了。

但是,most popular libraries in Java也支持将数字解释为BigDecimal:

BigDecimal涵盖了doublelong的范围,并且具有解决OP问题的实际.remainder() method。如果我们只想使用一个类来执行算术,并且BigDecimal的价格不被认为是一个大问题,那么这可能是一个可行的选择。