比较 Java 中的数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3214448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 17:29:33  来源:igfitidea点击:

Comparing Numbers in Java

javacomparisonnumbers

提问by David

In Java, all numeric types extend from java.lang.Number. Would it be a good idea to have a method like the following:

在 Java 中,所有数字类型都从 java.lang.Number 扩展而来。有一个像下面这样的方法是个好主意吗:

public boolean areEqual(Number first, Number second) {
    if (first != null && second != null) {
        return first.equals(second);
    }
}

I'm concerned about cases where a double 2.00000 does not equal an int 2. Are these handled by the built-in equals? If not, is there any way to write a simple number compare function in java? (external libraries such as apache commons are ok)

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

采纳答案by polygenelubricants

A Doubleis NEVERequalsto an Integer. Moreover, a doubleis not the same as a Double.

一个Double从来没有equalsInteger。此外, adouble与 a 不同Double

Java has primitive types and reference types. The truly numeric types in Java do not extend from Number, because they're primitives.

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

You may want to consider a system where you're not mixing types, because that usually will cause a lot of trouble with implicit/explicit conversions that may/may not lose information, etc.

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

Related questions

相关问题

On intvs Integer:

intVS Integer

On Numbercomparison:

Number对比:

See also

也可以看看



On mixed-type computation

关于混合型计算

Mixed-type computation is the subject of at least 4 puzzles in Java Puzzlers.

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

Here are various excerpts:

以下是各种摘录:

it is generally best to avoid mixed-type computations [...] because they are inherently confusing [...] Nowhere is this more apparent than in conditional expressions. Mixed-type comparisons are always confusing because the system is forced to promote one operand to match the type of the other. The conversion is invisible and may not yield the results that you expect

Prescription: Avoid computations that mix integral and floating-point types. Prefer integral arithmetic to floating-point.

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

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

回答by Pops

The specific method you suggest would fail, because it's using equals()inherited from Object. That is, it would check to see if the Numberobjectswere the same, not whether their valueswere the same.

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

If that was just an illustrative example, I will update my answer.

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

polygene's answer actually pretty much covers the ground I was heading for. You may also be interested in this question: Why doesn't java.lang.Number implement Comparable?.

polygene 的答案实际上几乎涵盖了我正在前往的领域。您可能还对这个问题感兴趣:为什么 java.lang.Number 不实现 Comparable?.

回答by Richard

you cannot call

你不能打电话

number.equals(number2);

because, if number is a Double and number2 is an Integer, they will not be of the same class and you will get an exception telling you of that fact.

因为,如果 number 是 Double 且 number2 是 Integer,则它们将不属于同一类,并且您将收到一个异常告诉您该事实。

You could write a comparison class yourself that accepts Number objects, but you will have to take into account the different subclasses of Number

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

回答by Andrzej Doyle

If you want to know whether the object references are the same, then the existing methods fit the bill. A Doublerepresenting 2.0and an Integerrepresenting 2are definitely different objects, and certainly not interchangeable in a general sense.

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

If you just want to know whether the numeric values are the same, you can use the Number.doubleValue()method to convert both numbers to doubles, then compare those numbers together (probably allowing for a small tolerance, as most numbers are represented inexactly, such as 1.99999999996583 for what should be 2, depending on the intermediate calculation steps). Something like the following:

如果您只想知道数值是否相同,您可以使用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;
   }
}

回答by rsp

Comparing numbers between integer and floating point is almost never going to yield what you are after. If however this is a simple exercise, you could implement the comparison by comparing the string representations of the values, as in:

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

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

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

回答by Jay

On a tangent to a couple of the responses, may I suggest that instead of writing something like:

关于几个回答的切线,我可以建议而不是写一些类似的东西:

boolean compare(Object o1, Object o2)
{
  if (o1==null)
    return o2==null;
  if (o2==null)
    return false;
  return o1.equals(o2);
}

It's much more concise, and I believe slightly more efficient, to write:

写得更简洁,我相信效率更高:

boolean compare(Object o1, Object o2)
{
  return o1==o2 || o1!=null && o2!=null && o1.equals(o2);
}

If both are null, o1==o2 will return true. If they're not but they're the same object, that's fine too.

如果两者都为空,则 o1==o2 将返回 true。如果它们不是但它们是同一个对象,那也没关系。

Technically the o2!=null is not necessary for most implementations of equals, but if you were really being so generic as to do this on Objects as in the above example, you of course wouldn't know how every override was written.

从技术上讲,o2!=null 对于大多数 equals 的实现来说不是必需的,但是如果您真的像上面的示例那样在对象上如此通用,那么您当然不会知道每个覆盖是如何编写的。

回答by Lian

I know its an old topic, but.... To compare two Numbers in Java you can use the compareTo method from BigDecimal. BigDecimal can hold everything from short until double or BigInteger, so its the perfect class for this.

我知道这是一个古老的话题,但是......要比较 Java 中的两个数字,您可以使用 BigDecimal 中的 compareTo 方法。BigDecimal 可以保存从 short 到 double 或 BigInteger 的所有内容,因此它是完美的类。

So you can try to write something like this:

所以你可以尝试写这样的东西:

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

This is surely not the best approach regarding to performance. The following tests worked so far, at least with JDK7:

这肯定不是关于性能的最佳方法。到目前为止,以下测试有效,至少对于 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);

回答by Ghareeb Nawaz

    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;

}