用Java比较数字

用Java比较数字,java,comparison,numbers,Java,Comparison,Numbers,在Java中,所有数字类型都从Java.lang.Number扩展而来。采用以下方法是否是一个好主意: public boolean areEqual(Number first, Number second) { if (first != null && second != null) { return first.equals(second); } } private static final double EPSILON = 0.000000

在Java中,所有数字类型都从Java.lang.Number扩展而来。采用以下方法是否是一个好主意:

public boolean areEqual(Number first, Number second) {
    if (first != null && second != null) {
        return first.equals(second);
    }
}
private static final double EPSILON = 0.000000000000001d;    

public static boolean areEquivalentNumbers(Number a, Number b)
{
   if (a == null)
   {
      return b == null;
   }
   else if (b == null)
   {
      return false;
   }
   else
   {
      return Math.abs(a.doubleValue() - b.doubleValue()) < EPSILON;
   }
}

我关心的是双精度2.00000不等于整数2的情况。这些都是由内置的equals处理的吗?如果没有,有没有办法用java编写一个简单的数字比较函数?(外部库,如apache commons是可以的)

A
Double
从不
等于
整数
。此外,
double
double
不同

Java有基元类型和引用类型。Java中真正的数字类型不是从
Number
扩展而来的,因为它们是原语

您可能想考虑一个不混合类型的系统,因为这通常会导致隐式/显式转换(可能会丢失信息等)的大量麻烦。 相关问题 在

int
vs
Integer
上:

关于编号比较:

另见
  • 数值类型为整数类型和浮点类型。 整数类型有
    byte
    short
    int
    long
    char
    。 浮点类型是
    float
    double


关于混合型计算 混合型计算是计算机中至少4个难题的主题

以下是各种摘录:

通常最好避免混合类型的计算[…],因为它们本身就容易混淆[…]这一点在条件表达式中最为明显。混合类型比较总是令人困惑,因为系统被迫升级一个操作数以匹配另一个操作数的类型。转换是不可见的,可能不会产生预期的结果

处方:避免混合整数和浮点类型的计算。喜欢整数运算而不是浮点运算


您建议的特定方法将失败,因为它使用从
对象继承的
equals()
。也就是说,它将检查
Number
对象是否相同,而不是它们的值是否相同

如果这只是一个说明性的例子,我将更新我的答案

polygene的答案实际上几乎涵盖了我想要的领域。您可能还对这个问题感兴趣:。

您不能打电话

number.equals(number2);
因为,如果number是一个Double,number2是一个整数,它们将不属于同一个类,您将得到一个异常,告诉您这一事实


您可以自己编写一个接受Number对象的比较类,但是您必须考虑Number的不同子类。如果您想知道对象引用是否相同,那么现有的方法符合要求。表示
2.0
Double
和表示
2
Integer
绝对是不同的对象,在一般意义上肯定不能互换

如果您只想知道数值是否相同,可以使用该方法将两个数字转换为双精度,然后将这些数字一起比较(可能允许较小的公差,因为大多数数字表示不准确,例如1.9999996583表示应为2的数字,具体取决于中间计算步骤)。如下所示:

public boolean areEqual(Number first, Number second) {
    if (first != null && second != null) {
        return first.equals(second);
    }
}
private static final double EPSILON = 0.000000000000001d;    

public static boolean areEquivalentNumbers(Number a, Number b)
{
   if (a == null)
   {
      return b == null;
   }
   else if (b == null)
   {
      return false;
   }
   else
   {
      return Math.abs(a.doubleValue() - b.doubleValue()) < EPSILON;
   }
}
private static final double EPSILON=0.000000000000001d;
公共静态布尔值AreequivalentNumber(数字a、数字b)
{
如果(a==null)
{
返回b==null;
}
else如果(b==null)
{
返回false;
}
其他的
{
返回Math.abs(a.doubleValue()-b.doubleValue())
比较整数和浮点之间的数字几乎永远不会得到你想要的结果。但是,如果这是一个简单的练习,则可以通过比较值的字符串表示形式来实现比较,如中所示:

public boolean areEqual(Number first, Number second) {
    if (first == null) {
        return second == null;
    }
    if (second == null) {
        return false;
    }

    return first.toString().equals(second.toString());
}

关于一些回答,我是否可以建议不要写这样的东西:

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的实现来说,null不是必需的,但是如果您真的像上面的示例那样对对象执行此操作,那么您当然不知道每个重写是如何编写的。

我知道这是一个老话题,但是。。。。 要在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);

System.out.println(新的Double(0).equals(新的Long(0))打印<代码>错误
;它不会抛出任何
异常
。有趣的方法!由于
String
操作效率低下,可能不适合进行大量比较。不起作用。((Number)0.0f).toString().equals(((Number)0).toString())==>False对于所有
Number
实现,首选
Type.valueOf(value)
新类型(value)
。它们都提供缓存,这将在大规模应用程序中节省内存。我刚刚否决了你的答案,因为使用doubleValue()将Long.MAX_值转换为BigDecimal会得到9223372036854775808,而不是9223372036854775807。从BigInteger到BigDecimal的转换更糟糕。为了正确起见,请遵循pickypg的建议,而不是调用BigDecimal.valueOf(long)和new BigDecimal(BigInteger)