比较Java中的数字

在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等外部库都可以)

Double 永远不 equals Integer 。 而且, doubleDouble

Java具有原始类型和引用类型。 Java中真正的数字类型不会从Number扩展,因为它们是原语。

您可能想要考虑一个不混合类型的系统,因为这通常会导致很多可能/可能不会丢失信息的隐式/显式转换的麻烦等。

相关问题

int vs Integer

  • Java / C#中的int和Integer有什么区别?
  • Java完全面向对象吗?

Number比较:

  • 为什么java.lang.Number没有实现Comparable
  • 比较两个通用数字的值

也可以看看

  • Java语言指南/ Autoboxing
  • JLS 4.2 4.2原始类型和值

    数值类型是整数类型和浮点类型。 整数类型是byteshortintlongchar 。 浮点类型是floatdouble


关于混合型计算

混合型计算是Java Puzzlers中至少4个难题的主题。

以下是各种摘录:

通常最好避免混合型计算[…]因为它们本质上令人困惑[…]这在条件表达式中更为明显。 混合类型比较总是令人困惑,因为系统被迫提升一个操作数以匹配另一个操作数的类型。 转换是不可见的,可能无法产生您期望的结果

处方 :避免混合整数和浮点类型的计算。 首选积分算法到浮点数。

我知道它是一个古老的主题,但是……要比较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); 

您建议的具体方法将失败,因为它使用从Objectinheritance的equals() 。 也就是说,它会检查Number 对象是否相同,而不是它们的是否相同。

如果那只是一个说明性的例子,我会更新我的答案。

polygene的答案实际上几乎覆盖了我前进的基础。 您可能也对此问题感兴趣: 为什么java.lang.Number不能实现Comparable? 。

如果您想知道对象引用是否相同,那么现有方法符合要求。 表示2.0Double和表示2Integer绝对是不同的对象,并且在一般意义上肯定不可互换。

如果您只想知道数值是否相同,可以使用Number.doubleValue()方法将两个数字转换为双精度数,然后将这些数字进行比较(可能允许较小的容差,因为大多数数字都表示不准确例如1.99999999996583应该是2,取决于中间计算步骤)。 类似于以下内容:

 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; } } 

比较整数和浮点之间的数字几乎不会产生你想要的东西。 但是,如果这是一个简单的练习,您可以通过比较值的字符串表示来实现比较,如:

 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实现来说,o2!= null并不是必需的,但如果你真的如此通用,就像在上面的例子中那样对象,你当然不会知道每个覆盖是如何写的。

你不能打电话

 number.equals(number2); 

因为,如果number是一个Double而number2是一个Integer,它们将不属于同一个类,你会得到一个exception,告诉你这个事实。

您可以自己编写一个接受Number对象的比较类,但是您必须考虑Number的不同子类