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

我尝试使用modulo来检查例如:
public static boolean isMultipleOf(Number a,Number b){
返回%b == 0;
}



 但编译器不喜欢它:
& #xA;



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


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

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

谢谢!
答案 0 :(得分:1)
你可以这样做:
public static boolean isMultipleOf(Number a, Number b) {
return a.longValue() % b.longValue() == 0;
}
当然,这假设a
和b
是数学上的整数(如此短整数,整数或长整数)。您可以使用doubleValue()
代替,但要注意浮点代数比较...
答案 1 :(得分:1)
您可以使用doubleValue
方法将参数转换为double
并应用%
,例如:
private static boolean isMultipleOf(Number a, Number b){
return (a.doubleValue() % b.doubleValue()) == 0.0;
}
它也适用于int
和float
,例如:
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仅提供转换为基元的方法,而每个基元都不足以给出准确的答案。
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`.
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
?
现在OP声明使用了Number
因为数字来自JSON。这些数字通常只有long
或double
,因此类型检查方法就足够了。
但是,most popular libraries in Java也支持将数字解释为BigDecimal:
.getBigDecimal()
.getAsBigDecimal()
BigDecimal
字段javax.json
(JSR 353)有.bigDecimalValue()
BigDecimal涵盖了double
和long
的范围,并且具有解决OP问题的实际.remainder()
method。如果我们只想使用一个类来执行算术,并且BigDecimal的价格不被认为是一个大问题,那么这可能是一个可行的选择。