在Java中,所有数字类型都从java.lang.Number扩展。拥有如下方法是个好主意:
public boolean areEqual(Number first, Number second) {
if (first != null && second != null) {
return first.equals(second);
}
}
我担心双重2.00000不等于int 2的情况。这些是由内置等于处理吗?如果没有,有没有办法在java中编写一个简单的数字比较函数? (apache commons等外部库都可以)
答案 0 :(得分:38)
Double
从不 equals
到Integer
。此外,double
与Double
不同。
Java具有原始类型和引用类型。 Java中真正的数字类型不会从Number
扩展,因为它们是原语。
您可能需要考虑一个不混合类型的系统,因为这通常会导致隐藏/显式转换很多麻烦,可能会/可能不会丢失信息等。
在int
vs Integer
上:
开Number
比较:
数字类型是整数类型和浮点类型。 整数类型为
byte
,short
,int
以及long
和char
。 浮点类型为float
和double
。
混合型计算是Java Puzzlers中至少4个谜题的主题。
以下是各种摘录:
通常最好避免混合型计算[...],因为它们本质上令人困惑[...]这在条件表达式中更为明显。混合类型比较总是令人困惑,因为系统被迫提升一个操作数以匹配另一个操作数的类型。转换是不可见的,可能无法产生您期望的结果
处方:避免混合使用整数和浮点类型的计算。首选积分算术到浮点。
答案 1 :(得分:11)
我知道这是一个古老的话题,但...... 要比较Java中的两个数字,可以使用BigDecimal中的compareTo方法。 BigDecimal可以容纳从short到double或BigInteger的所有内容,因此它是完美的类。
所以你可以尝试写这样的东西:
public int compareTo(Number n1, Number n2) {
// ignoring null handling
BigDecimal b1 = new BigDecimal(n1.doubleValue());
BigDecimal b2 = new BigDecimal(n2.doubleValue());
return b1.compareTo(b2);
}
这肯定不是关于性能的最佳方法。 到目前为止,以下测试工作至少使用JDK7:
assertTrue(compareTo(new Integer(1), new Integer(2)) == -1);
assertTrue(compareTo(new Integer(1), new Double(2.0)) == -1);
assertTrue(compareTo(new Integer(1), new Double(Double.MAX_VALUE)) == -1);
assertTrue(compareTo(new Integer(1), new Double(Double.MIN_VALUE)) == 1);
assertTrue(compareTo(new Integer(1), new Double(1.000001)) == -1);
assertTrue(compareTo(new Integer(1), new Double(1.000)) == 0);
assertTrue(compareTo(new Integer(1), new Double(0.25*4)) == 0);
assertTrue(compareTo(new Integer(1), new AtomicLong(1)) == 0);
答案 2 :(得分:6)
您建议的具体方法会失败,因为它使用的是继承自equals()
的{{1}}。也就是说,它会检查Object
对象是否相同,而不是它们的值是否相同。
如果那只是一个说明性的例子,我会更新我的答案。
polygene的答案实际上几乎覆盖了我前进的基础。您可能也对此问题感兴趣:Why doesn't java.lang.Number implement Comparable?。
答案 3 :(得分:4)
如果您想知道对象引用是否相同,那么现有方法符合要求。代表Double
的{{1}}和代表2.0
的{{1}}绝对是不同的对象,并且在一般意义上肯定不可互换。
如果您只是想知道数值是否相同,可以使用Number.doubleValue()方法将两个数字转换为双数,然后将这些数字进行比较(可能允许较小的容差,因为大多数数字表示不完整,例如1.99999999996583,应该是2,取决于中间计算步骤)。如下所示:
Integer
答案 4 :(得分:1)
比较整数和浮点之间的数字几乎不会产生你想要的东西。但是,如果这是一个简单的练习,您可以通过比较值的字符串表示来实现比较,如:
public boolean areEqual(Number first, Number second) {
if (first == null) {
return second == null;
}
if (second == null) {
return false;
}
return first.toString().equals(second.toString());
}
答案 5 :(得分:1)
在几个回复的切线上,我可以建议不要写下这样的内容:
boolean compare(Object o1, Object o2)
{
if (o1==null)
return o2==null;
if (o2==null)
return false;
return o1.equals(o2);
}
它更简洁,我相信写得更有效率:
boolean compare(Object o1, Object o2)
{
return o1==o2 || o1!=null && o2!=null && o1.equals(o2);
}
如果两者都为null,则o1 == o2将返回true。如果他们不是,但他们是同一个对象,那也没关系。
从技术上讲,对于大多数equals实现来说,o2!= null并不是必需的,但是如果你真的如此通用,就像在上面的例子中那样对象,你当然不会知道每个覆盖是如何写的
答案 6 :(得分:0)
public static boolean compareTo(Number d1, Number d2) {
Double num1=d1.doubleValue();
Double num2=d2.doubleValue();
if(Double.compare(num1, num2)==0)
return true;
else
return false;
}
OR
public static boolean compareTo(Number d1, Number d2) {
if(d1.doubleValue()==d2.doubleValue())
return true;
else
return false;
}
答案 7 :(得分:-1)
你不能打电话
number.equals(number2);
因为,如果number是一个Double而number2是一个Integer,它们将不属于同一个类,你会得到一个异常,告诉你这个事实。
您可以自己编写一个接受Number对象的比较类,但是您必须考虑Number的不同子类