如何在Java中比较两个数字?

20

我想比较两个任意实例的Number,以找出哪一个更大。正如您所知,它们可以是整数、长整数或双精度浮点数,也可以是大整数或大十进制数。那该怎么办呢?

  1. Number没有实现Comparable
  2. 不能使用doubleValue(),因为从大整数或大十进制数中可能会有精度损失。

我真的必须进行实例测试和转换吗?一定有一些库可以做到这一点。但我已经检查过Apache Commons和Guava,没有找到合适的。

编辑1:评论指出:比较两个通用数字的值。它有一个解决方案,使用toString()将所有内容转换为BigDecimal。难道真的没有更好的方法吗?

编辑2:我刚刚发布了自己的答案作为对另一个问题的回答。它应该比已接受的答案更有效和健壮。


6
如何将任何内容转换为“BigDecimal”? - SJuan76
1
请参考答案和其中的链接:https://dev59.com/inA75IYBdhLWcg3wlqKh#3214469 - MicSim
1
为什么要比较任意数字类?它们为什么不是同一类型? - Peter Lawrey
好问题,一定要看看@MicSim提供的链接。 - UmNyobe
1
我同意SJuan76的观点。我最终也采用了将任何数字转换为BigDecimal并进行比较的方法。 - user330315
显示剩余6条评论
2个回答

18

您不能比较两个任意类型的Number实例,因为这可能是一个无限的操作。想象一下两个无理数,它们唯一的区别在于十亿分位上。你将不得不比较大约十亿个小数位。

您需要将您的Number实例转换为BigDecimal,必要时应进行四舍五入,然后再进行比较。


有趣的评论,谢谢。但由于这是一个库,决定何时何地进行舍入并不取决于我。 - rolve
4
那么,您应该让库的用户有可能定义要使用的舍入方式和所需的精度。 - SpaceTrucker

7
严格来说,数字是无法进行比较的。您需要首先定义比较的语义。由于提到了库的使用,您可能只想依赖于Number API所提供的内容。
因此,将其降低为比较longValue()或doubleValue()的值。我建议采用首先使用longValue()进行比较的方法,如果它们被证明是相等的,则同时比较doubleValue()(这样可以捕获长整型溢出,但在值不是浮点数时仍保持64位长整型精度):
public static int compare(Number n1, Number n2) {
    long l1 = n1.longValue();
    long l2 = n2.longValue();
    if (l1 != l2)
        return (l1 < l2 ? -1 : 1);
    return Double.compare(n1.doubleValue(), n2.doubleValue());
}

除此之外,其他的猜测都超出了Number API所提供的范围。对于标准的使用,上述代码应该运行得相当顺畅。是的,如果你传递的是BigInteger或BigDecimal,它们超出了Double值范围或具有超出53位尾数精度的差异,则会错误地被检测为相等,但就Number API而言,这个错误的结果可以被视为“正确”的。


我认为应该首先比较double值;否则,我认为NaN将在-1和下一个更大的值之间排序。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接