比较两个通用数字的值

发布于 2024-08-30 09:16:02 字数 389 浏览 12 评论 0原文

我想与 T extends Number 类型的变量进行比较。现在我想知道两个变量中哪个大于另一个或相等。不幸的是,我还不知道确切的类型,我只知道它将是 java.lang.Number 的子类型。我怎样才能做到这一点?

编辑:我尝试了使用TreeSet的另一种解决方法,它实际上适用于自然排序(当然它有效,Number的所有子类都实现可比较(AtomicInteger 和 AtomicLong 除外)。因此我会丢失重复的值。使用 List 时,由于绑定不匹配,Collection.sort() 将不接受我的列表。非常不满意。

I want to compare to variables, both of type T extends Number. Now I want to know which of the two variables is greater than the other or equal. Unfortunately I don't know the exact type yet, I only know that it will be a subtype of java.lang.Number. How can I do that?

EDIT: I tried another workaround using TreeSets, which actually worked with natural ordering (of course it works, all subclasses of Number implement Comparable except for AtomicInteger and AtomicLong). Thus I'll lose duplicate values. When using Lists, Collection.sort() will not accept my list due to bound mismatchs. Very unsatisfactory.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

如歌彻婉言 2024-09-06 09:16:02

这应该适用于所有扩展 Number 且与自身可比较的类。通过添加 &与 Sarmun 答案相比,您允许删除所有类型检查,并免费提供运行时类型检查和错误抛出。

class NumberComparator<T extends Number & Comparable> implements Comparator<T> {

    public int compare( T a, T b ) throws ClassCastException {
        return a.compareTo( b );
    }
}

This should work for all classes that extend Number, and are Comparable to themselves. By adding the & Comparable you allow to remove all the type checks and provides runtime type checks and error throwing for free when compared to Sarmun answer.

class NumberComparator<T extends Number & Comparable> implements Comparator<T> {

    public int compare( T a, T b ) throws ClassCastException {
        return a.compareTo( b );
    }
}
旧瑾黎汐 2024-09-06 09:16:02

一个可行的(但脆弱的)解决方案是这样的:

class NumberComparator implements Comparator<Number> {

    public int compare(Number a, Number b){
        return new BigDecimal(a.toString()).compareTo(new BigDecimal(b.toString()));
    }

}

不过,它仍然不是很好,因为它依赖于 toString 返回一个可由 BigDecimal 解析的值(标准 Java < code>Number 类可以,但 Number 合约不需要)。

编辑,七年后:正如评论中所指出的,(至少?)三种特殊情况 toString 可能会产生您需要考虑的情况:

A working (but brittle) solution is something like this:

class NumberComparator implements Comparator<Number> {

    public int compare(Number a, Number b){
        return new BigDecimal(a.toString()).compareTo(new BigDecimal(b.toString()));
    }

}

It's still not great, though, since it counts on toString returning a value parsable by BigDecimal (which the standard Java Number classes do, but which the Number contract doesn't demand).

Edit, seven years later: As pointed out in the comments, there are (at least?) three special cases toString can produce that you need to take into regard:

忆依然 2024-09-06 09:16:02

在提出类似问题并研究此处的答案后,我得出了以下结论。我认为它比 gustafc 给出的解决方案更高效、更健壮:

public int compare(Number x, Number y) {
    if (isSpecial(x) || isSpecial(y))
        return Double.compare(x.doubleValue(), y.doubleValue());
    else
        return toBigDecimal(x).compareTo(toBigDecimal(y));
}

private static boolean isSpecial(Number x) {
    var specialDouble = x instanceof Double d
            && (Double.isNaN(d) || Double.isInfinite(d));
    var specialFloat = x instanceof Float f
            && (Float.isNaN(f) || Float.isInfinite(f));
    return specialDouble || specialFloat;
}

private static BigDecimal toBigDecimal(Number number) {
    if (number instanceof BigDecimal d)
        return d;
    if (number instanceof BigInteger i)
        return new BigDecimal(i);
    if (number instanceof Byte || number instanceof Short
            || number instanceof Integer || number instanceof Long)
        return new BigDecimal(number.longValue());
    if (number instanceof Float || number instanceof Double)
        return new BigDecimal(number.doubleValue());
    
    try {
        return new BigDecimal(number.toString());
    } catch(NumberFormatException e) {
        throw new RuntimeException("The given number (\"" + number + "\" of class " + number.getClass().getName() + ") does not have a parsable string representation", e);
    }
}

After having asked a similar question and studying the answers here, I came up with the following. I think it is more efficient and more robust than the solution given by gustafc:

public int compare(Number x, Number y) {
    if (isSpecial(x) || isSpecial(y))
        return Double.compare(x.doubleValue(), y.doubleValue());
    else
        return toBigDecimal(x).compareTo(toBigDecimal(y));
}

private static boolean isSpecial(Number x) {
    var specialDouble = x instanceof Double d
            && (Double.isNaN(d) || Double.isInfinite(d));
    var specialFloat = x instanceof Float f
            && (Float.isNaN(f) || Float.isInfinite(f));
    return specialDouble || specialFloat;
}

private static BigDecimal toBigDecimal(Number number) {
    if (number instanceof BigDecimal d)
        return d;
    if (number instanceof BigInteger i)
        return new BigDecimal(i);
    if (number instanceof Byte || number instanceof Short
            || number instanceof Integer || number instanceof Long)
        return new BigDecimal(number.longValue());
    if (number instanceof Float || number instanceof Double)
        return new BigDecimal(number.doubleValue());
    
    try {
        return new BigDecimal(number.toString());
    } catch(NumberFormatException e) {
        throw new RuntimeException("The given number (\"" + number + "\" of class " + number.getClass().getName() + ") does not have a parsable string representation", e);
    }
}
走过海棠暮 2024-09-06 09:16:02

一种可能适合您的解决方案是不使用 T extends Number ,而是使用 T extends Number & 。可比较。此类型意味着:“T 只能设置为实现两个接口的类型。”

这使您可以编写适用于所有可比较数字的代码。静态类型且优雅。

这与 BennyBoy 提出的解决方案相同,但它适用于各种方法,而不仅仅是比较器类。

public static <T extends Number & Comparable<T>> void compfunc(T n1, T n2) {
    if (n1.compareTo(n2) > 0) System.out.println("n1 is bigger");
}

public void test() {
    compfunc(2, 1); // Works with Integer.
    compfunc(2.0, 1.0); // And all other types that are subtypes of both Number and Comparable.
    compfunc(2, 1.0); // Compilation error! Different types.
    compfunc(new AtomicInteger(1), new AtomicInteger(2)); // Compilation error! Not subtype of Comparable
}

One solution that might work for you is to work not with T extends Number but with T extends Number & Comparable. This type means: "T can only be set to types that implements both the interfaces."

That allows you to write code that works with all comparable numbers. Statically typed and elegant.

This is the same solution that BennyBoy proposes, but it works with all kinds of methods, not only with comparator classes.

public static <T extends Number & Comparable<T>> void compfunc(T n1, T n2) {
    if (n1.compareTo(n2) > 0) System.out.println("n1 is bigger");
}

public void test() {
    compfunc(2, 1); // Works with Integer.
    compfunc(2.0, 1.0); // And all other types that are subtypes of both Number and Comparable.
    compfunc(2, 1.0); // Compilation error! Different types.
    compfunc(new AtomicInteger(1), new AtomicInteger(2)); // Compilation error! Not subtype of Comparable
}
平生欢 2024-09-06 09:16:02

最“通用”的 Java 原始数字是 double,因此

a.doubleValue() > b.doubleValue()

在大多数情况下简单地使用应该足够了,但是......将数字转换为 double 时,这里存在一些微妙的问题。例如,使用 BigInteger: 可能会

    BigInteger a = new BigInteger("9999999999999992");
    BigInteger b = new BigInteger("9999999999999991");
    System.out.println(a.doubleValue() > b.doubleValue());
    System.out.println(a.doubleValue() == b.doubleValue());

出现以下结果:

false
true

尽管我预计这是非常极端的情况,但这是可能的。不,不存在 100% 准确的通用方法。 Number 接口没有像精确值()这样的方法转换为某种能够以完美的方式表示数字而不会丢失任何信息的类型。

实际上,一般来说,拥有如此完美的数字是不可能的 - 例如,使用有限空间的任何算术来表示数字 Pi 是不可能的。

The most "generic" Java primitive number is double, so using simply

a.doubleValue() > b.doubleValue()

should be enough in most cases, but... there are subtle issues here when converting numbers to double. For example the following is possible with BigInteger:

    BigInteger a = new BigInteger("9999999999999992");
    BigInteger b = new BigInteger("9999999999999991");
    System.out.println(a.doubleValue() > b.doubleValue());
    System.out.println(a.doubleValue() == b.doubleValue());

results in:

false
true

Although I expect this to be very extreme case this is possible. And no - there is no generic 100% accurate way. Number interface have no method like exactValue() converting to some type able to represent number in perfect way without loosing any information.

Actually having such perfect numbers is impossible in general - for example representing number Pi is impossible using any arithmetic using finite space.

篱下浅笙歌 2024-09-06 09:16:02

这应该适用于所有扩展 Number 且与自身可比较的类。

class NumberComparator<T extends Number> implements Comparator<T> {

    public int compare(T a, T b){
        if (a instanceof Comparable) 
            if (a.getClass().equals(b.getClass()))
                return ((Comparable<T>)a).compareTo(b);        
        throw new UnsupportedOperationException();
    }
}

This should work for all classes that extend Number, and are Comparable to themselves.

class NumberComparator<T extends Number> implements Comparator<T> {

    public int compare(T a, T b){
        if (a instanceof Comparable) 
            if (a.getClass().equals(b.getClass()))
                return ((Comparable<T>)a).compareTo(b);        
        throw new UnsupportedOperationException();
    }
}
酒几许 2024-09-06 09:16:02
if(yourNumber instanceof Double) {
    boolean greaterThanOtherNumber = yourNumber.doubleValue() > otherNumber.doubleValue();
    // [...]
}

注意: instanceof 检查不一定需要 - 取决于您想要如何准确地比较它们。当然,您可以简单地始终使用 .doubleValue(),因为每个 Number 都应该提供列出的方法 此处

编辑:正如评论中所述,您将(总是)必须检查 BigDecimal 和朋友。但他们提供了一个 .compareTo() 方法:

if(yourNumber instanceof BigDecimal && otherNumber instanceof BigDecimal) { 
    boolean greaterThanOtherNumber = ((BigDecimal)yourNumber).compareTo((BigDecimal)otherNumber) > 0;
} 
if(yourNumber instanceof Double) {
    boolean greaterThanOtherNumber = yourNumber.doubleValue() > otherNumber.doubleValue();
    // [...]
}

Note: The instanceof check isn't necessarily needed - depends on how exactly you want to compare them. You could of course simply always use .doubleValue(), as every Number should provide the methods listed here.

Edit: As stated in the comments, you will (always) have to check for BigDecimal and friends. But they provide a .compareTo() method:

if(yourNumber instanceof BigDecimal && otherNumber instanceof BigDecimal) { 
    boolean greaterThanOtherNumber = ((BigDecimal)yourNumber).compareTo((BigDecimal)otherNumber) > 0;
} 
谁与争疯 2024-09-06 09:16:02

您可以简单地使用Number 的 doubleValue() 方法来比较它们;但是您可能会发现结果不够准确,无法满足您的需求。

You can simply use Number's doubleValue() method to compare them; however you may find the results are not accurate enough for your needs.

单身情人 2024-09-06 09:16:02

这个呢?绝对不好,但它处理提到的所有必要情况。

public class SimpleNumberComparator implements Comparator<Number>
    {
        @Override
        public int compare(Number o1, Number o2)
        {
            if(o1 instanceof Short && o2 instanceof Short)
            {
                return ((Short) o1).compareTo((Short) o2);
            }
            else if(o1 instanceof Long && o2 instanceof Long)
            {
                return ((Long) o1).compareTo((Long) o2);
            }
            else if(o1 instanceof Integer && o2 instanceof Integer)
            {
                return ((Integer) o1).compareTo((Integer) o2);
            }
            else if(o1 instanceof Float && o2 instanceof Float)
            {
                return ((Float) o1).compareTo((Float) o2);
            }
            else if(o1 instanceof Double && o2 instanceof Double)
            {
                return ((Double) o1).compareTo((Double) o2);
            }
            else if(o1 instanceof Byte && o2 instanceof Byte)
            {
                return ((Byte) o1).compareTo((Byte) o2);
            }
            else if(o1 instanceof BigInteger && o2 instanceof BigInteger)
            {
                return ((BigInteger) o1).compareTo((BigInteger) o2);
            }
            else if(o1 instanceof BigDecimal && o2 instanceof BigDecimal)
            {
                return ((BigDecimal) o1).compareTo((BigDecimal) o2);
            }
            else
            {
                throw new RuntimeException("Ooopps!");
            }

        }

    }

What about this one? Definitely not nice, but it deals with all necessary cases mentioned.

public class SimpleNumberComparator implements Comparator<Number>
    {
        @Override
        public int compare(Number o1, Number o2)
        {
            if(o1 instanceof Short && o2 instanceof Short)
            {
                return ((Short) o1).compareTo((Short) o2);
            }
            else if(o1 instanceof Long && o2 instanceof Long)
            {
                return ((Long) o1).compareTo((Long) o2);
            }
            else if(o1 instanceof Integer && o2 instanceof Integer)
            {
                return ((Integer) o1).compareTo((Integer) o2);
            }
            else if(o1 instanceof Float && o2 instanceof Float)
            {
                return ((Float) o1).compareTo((Float) o2);
            }
            else if(o1 instanceof Double && o2 instanceof Double)
            {
                return ((Double) o1).compareTo((Double) o2);
            }
            else if(o1 instanceof Byte && o2 instanceof Byte)
            {
                return ((Byte) o1).compareTo((Byte) o2);
            }
            else if(o1 instanceof BigInteger && o2 instanceof BigInteger)
            {
                return ((BigInteger) o1).compareTo((BigInteger) o2);
            }
            else if(o1 instanceof BigDecimal && o2 instanceof BigDecimal)
            {
                return ((BigDecimal) o1).compareTo((BigDecimal) o2);
            }
            else
            {
                throw new RuntimeException("Ooopps!");
            }

        }

    }
£噩梦荏苒 2024-09-06 09:16:02

在我的用例中,我正在寻找一个通用的Comparator,它可以与自动装箱基元(64位最大精度)一起使用,而不是像BigIntegerBigDecimal这样的任意精度类型。这是第一次尝试。

public class PrimitiveComparator implements Comparator<Number> {

  @Override
  public int compare(Number a, Number b) {
    if (a == b)
      return 0;
    double aD = a.doubleValue();
    double bD = b.doubleValue();
    int comp = Double.compare(aD, bD);
    if (comp == 0 && inLongBounds(aD))
      comp = Long.compare(a.longValue(), b.longValue());
    return comp;
  }
  
  private boolean inLongBounds(double value) {
    return
        Double.compare(value, Long.MAX_VALUE) <= 0 &&
        Double.compare(value, Long.MIN_VALUE) >= 0;
  }
}

目标是能够比较混合类型(例如,FloatLong)。这也应该适用于那些 AtomicXxx 类型(或任何使用不超过 64 位的手动 Number 子类)。

在此排序中,顺便说一句,Double.NaN > Double.POSITVE_INFINITY > {其他一切}

In my use case, I was looking for a general Comparator that works with the autoboxed primitives (64 bit max precision), not arbitrary precision types like BigInteger and BigDecimal. Here's a first shot at it..

public class PrimitiveComparator implements Comparator<Number> {

  @Override
  public int compare(Number a, Number b) {
    if (a == b)
      return 0;
    double aD = a.doubleValue();
    double bD = b.doubleValue();
    int comp = Double.compare(aD, bD);
    if (comp == 0 && inLongBounds(aD))
      comp = Long.compare(a.longValue(), b.longValue());
    return comp;
  }
  
  private boolean inLongBounds(double value) {
    return
        Double.compare(value, Long.MAX_VALUE) <= 0 &&
        Double.compare(value, Long.MIN_VALUE) >= 0;
  }
}

The objective is to be able to compare mixed types (e.g. Floats against Longs). This should also work with those AtomicXxx types (or any hand rolled Number subclass that uses no more than 64 bits).

In this ordering, btw, Double.NaN > Double.POSITVE_INFINITY > { everything else }.

月朦胧 2024-09-06 09:16:02

假设您有一些方法,例如:

public <T extends Number> T max (T a, T b) {
   ...
   //return maximum of a and b
}

如果您知道只有整数、长整数和双精度数可以作为参数传递,那么您可以将方法签名更改为:

public <T extends Number> T max(double a, double b) {
   return (T)Math.max (a, b);
}

这适用于字节、短整型、整数、长整型和双精度型。

如果您假设可以传递 BigInteger 或 BigDecimal 或浮点数和双精度数的混合,那么您无法创建一种通用方法来比较所有这些类型的参数。

Let's assume that you have some method like:

public <T extends Number> T max (T a, T b) {
   ...
   //return maximum of a and b
}

If you know that there are only integers, longs and doubles can be passed as parameters then you can change method signature to:

public <T extends Number> T max(double a, double b) {
   return (T)Math.max (a, b);
}

This will work for byte, short, integer, long and double.

If you presume that BigInteger's or BigDecimal's or mix of floats and doubles can be passed then you cannot create one common method to compare all these types of parameters.

踏月而来 2024-09-06 09:16:02

如果您的 Number 实例从不是原子的(即 AtomicInteger),那么您可以执行以下操作:

private Integer compare(Number n1, Number n2) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

 Class<? extends Number> n1Class = n1.getClass();
 if (n1Class.isInstance(n2)) {
  Method compareTo = n1Class.getMethod("compareTo", n1Class);
  return (Integer) compareTo.invoke(n1, n2);
 }

 return -23;
}

这是因为所有非原子 Number 都实现了 Comparable

编辑

由于反思,这是昂贵的:我知道

编辑2

这当然不考虑您想要将小数与整数或类似的情况进行比较的情况。 ..

编辑3

这假设没有自定义的 Number 后代不实现 Comparable (感谢@DJClayworth)

If your Number instances are never Atomic (ie AtomicInteger) then you can do something like:

private Integer compare(Number n1, Number n2) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

 Class<? extends Number> n1Class = n1.getClass();
 if (n1Class.isInstance(n2)) {
  Method compareTo = n1Class.getMethod("compareTo", n1Class);
  return (Integer) compareTo.invoke(n1, n2);
 }

 return -23;
}

This is since all non-Atomic Numbers implement Comparable

EDIT:

This is costly due to reflection: I know

EDIT 2:

This of course does not take of a case in which you want to compare decimals to ints or some such...

EDIT 3:

This assumes that there are no custom-defined descendants of Number that do not implement Comparable (thanks @DJClayworth)

从﹋此江山别 2024-09-06 09:16:02

似乎不可能以其他方式比较 Number 对象或处理数字与泛型,但是,好消息是只有六种基本数字类型,因此实现看似通用的功能可能会很麻烦实现它,但对最终用户来说看起来不错。

这就是我的实现方式:

public class LongNumber {
    public int compareTo(byte n) {
        return Long.compare(number, ((Byte)n).longValue());
    }
    public int compareTo(short n) {
        return Long.compare(number, ((Short)n).longValue());
    }
    public int compareTo(int n) {
        return Long.compare(number, ((Integer)n).longValue());
    }
    public int compareTo(long n) {
        return Long.compare(number, n);
    }
    public int compareTo(float n) {
        return Double.compare(number.doubleValue(), ((Float)n).doubleValue());
    }
    public int compareTo(double n) {
        return Double.compare(number.doubleValue(), n);
    }

    public LongNumber(byte number) { this(((Byte)number).longValue()); }
    public LongNumber(short number) { this(((Short)number).longValue()); }
    public LongNumber(int number) { this(((Integer)number).longValue()); }
    public LongNumber(long number) { this.number = number; }

    private final Long number;
}

此类包装整数(字节、短整型、整数、长整型)并将它们全部转换为长整型。我选择在方法中使用基元以避免进行 null 检查,但将数字存储为 Long 以便与 float进行比较更容易加倍。

作为该类的用户,您会执行以下操作:

byte num = 64;
final LongNumber longNumber = new LongNumber(num);
System.out.println("123456L != 64: " + (longNumber.compareTo(123456L) != 0));

System.out.println("Even though (byte)123456L = " + ((Long)123456L).byteValue());

System.out.println("Is 64 > PI? " + (longNumber.compareTo(Math.PI) > 0));

我有另一个用于浮点值的类,其中我使用 Double.compare() 进行所有比较:

public class DoubleNumber {
    public int compareTo(byte n) {
        return Double.compare(number, ((Byte)n).doubleValue());
    }
    public int compareTo(short n) {
        return Double.compare(number, ((Short)n).doubleValue());
    }
    public int compareTo(int n) {
        return Double.compare(number, ((Integer)n).doubleValue());
    }
    public int compareTo(long n) {
        return Double.compare(number, ((Long)n).doubleValue());
    }
    public int compareTo(float n) {
        return Double.compare(number, ((Float)n).doubleValue());
    }
    public int compareTo(double n) {
        return Double.compare(number, n);
    }

    public DoubleNumber(float number) { this(((Float)number).doubleValue()); }
    public DoubleNumber(double number) { this.number = number; }

    private final Double number;
}

如果您想更通用地工作使用数字,您可以为类(或实际上六个)创建一个工厂方法,它将输入参数包装在正确的包装类中:

public static LongNumber of(int n) {
    return new LongNumber(n);
}
public static DoubleNumber of(float n) {
    return new DoubleNumber(n);
}

您甚至可以创建一个静态比较方法,例如:

public static int compare(double x, int y) {
    return new DoubleNumber(x).compareTo(y);
}

不过,您需要实现其中的 36 个。再说一遍,编码时很辛苦,但使用时非常好,如果 Java 人员可以像他们所做的那样执行 List.of(...) (至少在 Java 17 中) ,也许 36 个方法并不是那么极端...

但是,如果您愿意实现 36 个静态方法,您可能想要执行以下操作:

public static int compare(double x, int y) {
    return Double.compare(x, ((Integer) y).doubleValue());
}

我的用例是我有一个可能想要使用的数字一次,所以对我来说,将它包装在一个只需要实现 6 个compareTo 方法的类中是最有意义的。

It doesn't seem as if it is possible to compare Number objects or handle numbers with generics in other ways, however, the good news is that there are only six primitive number types, so implementing functionality that seems to be generic may be cumbersome when implementing it but can look nice to the final user.

This is how I've implemented this:

public class LongNumber {
    public int compareTo(byte n) {
        return Long.compare(number, ((Byte)n).longValue());
    }
    public int compareTo(short n) {
        return Long.compare(number, ((Short)n).longValue());
    }
    public int compareTo(int n) {
        return Long.compare(number, ((Integer)n).longValue());
    }
    public int compareTo(long n) {
        return Long.compare(number, n);
    }
    public int compareTo(float n) {
        return Double.compare(number.doubleValue(), ((Float)n).doubleValue());
    }
    public int compareTo(double n) {
        return Double.compare(number.doubleValue(), n);
    }

    public LongNumber(byte number) { this(((Byte)number).longValue()); }
    public LongNumber(short number) { this(((Short)number).longValue()); }
    public LongNumber(int number) { this(((Integer)number).longValue()); }
    public LongNumber(long number) { this.number = number; }

    private final Long number;
}

This class wraps integers (byte, short, int, long) and converts them all to Long. I've opted to use primitives in the methods to avoid having to do null checks but stored the number as a Long in order to make the comparisons to float and double easier.

As a user of the class, you'd do something like:

byte num = 64;
final LongNumber longNumber = new LongNumber(num);
System.out.println("123456L != 64: " + (longNumber.compareTo(123456L) != 0));

System.out.println("Even though (byte)123456L = " + ((Long)123456L).byteValue());

System.out.println("Is 64 > PI? " + (longNumber.compareTo(Math.PI) > 0));

I have another class for floating point values where I do all comparisons using Double.compare() instead:

public class DoubleNumber {
    public int compareTo(byte n) {
        return Double.compare(number, ((Byte)n).doubleValue());
    }
    public int compareTo(short n) {
        return Double.compare(number, ((Short)n).doubleValue());
    }
    public int compareTo(int n) {
        return Double.compare(number, ((Integer)n).doubleValue());
    }
    public int compareTo(long n) {
        return Double.compare(number, ((Long)n).doubleValue());
    }
    public int compareTo(float n) {
        return Double.compare(number, ((Float)n).doubleValue());
    }
    public int compareTo(double n) {
        return Double.compare(number, n);
    }

    public DoubleNumber(float number) { this(((Float)number).doubleValue()); }
    public DoubleNumber(double number) { this.number = number; }

    private final Double number;
}

If you want to work even more generically with numbers you could create a factory method for the classes (or actually six) that would wrap the input parameter in the correct wrapper class:

public static LongNumber of(int n) {
    return new LongNumber(n);
}
public static DoubleNumber of(float n) {
    return new DoubleNumber(n);
}

You could even create a static compare method like:

public static int compare(double x, int y) {
    return new DoubleNumber(x).compareTo(y);
}

Though, you'd need to implement 36 of them. Again, hard work when coding it, but pretty nice when using it, and if the Java-people can do List.of(...) like they've done (at least in Java 17), maybe 36 methods aren't such an extreme...

However, if you're willing to implement 36 static methods you might want to do something like:

public static int compare(double x, int y) {
    return Double.compare(x, ((Integer) y).doubleValue());
}

My use case is that I have a number I might want to work with more than once, so for me, wrapping it in a class where I only have to implement 6 compareTo-methods made the most sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文