【问题标题】:java number exceeds long.max_value - how to detect?java数字超过long.max_value - 如何检测?
【发布时间】:2012-09-10 08:42:54
【问题描述】:

我在检测两个数字的和/乘是否超过长整数的最大值时遇到问题。
示例代码:

long a = 2 * Long.MAX_VALUE;
System.out.println("long.max * smth > long.max... or is it? a=" + a);

这给了我-2,而我希望它会抛出一个NumberFormatException...

有没有一种简单的方法来完成这项工作?因为我有一些代码在嵌套的 IF 块中进行乘法运算或在循环中进行加法运算,我不想在每个 IF 或循环内添加更多的 IF。

编辑:哦,好吧,似乎另一个问题的这个答案最适合我的需要:https://stackoverflow.com/a/9057367/540394
我不想装箱/拆箱,因为它增加了不必要的开销,而且这种方式很短,这对我来说是一个巨大的优势。我将编写两个简短的函数来执行这些检查并返回最小或最大长度。

Edit2:根据我上面链接的答案,这是将 long 限制为其最小值/最大值的函数:

/**
 * @param a : one of the two numbers added/multiplied
 * @param b : the other of the two numbers
 * @param c : the result of the addition/multiplication
 * @return the minimum or maximum value of a long integer if addition/multiplication of a and b is less than Long.MIN_VALUE or more than Long.MAX_VALUE
 */
public static long limitLong(long a, long b, long c)
{
    return (((a > 0) && (b > 0) && (c <= 0))
        ? Long.MAX_VALUE
        : (((a < 0) && (b < 0) && (c >= 0)) ? Long.MIN_VALUE : c));
}

如果您认为这是错误的,请告诉我。

【问题讨论】:

  • +1。应该有一些允许整数溢出检测的库。
  • 或特殊块(类似于 finally?),可以帮助开发人员为在其中执行的所有数学代码启用溢出错误行为。我相信 C# 有一个。编辑:找到了,checked and unchecked blocks in C#
  • 好吧,C# 似乎在溢出时抛出错误(我更喜欢沉默和对我没有意义的错误结果)...
  • 添加了检查最小/最大溢出的功能,有人可以检查一下吗?

标签: java numbers


【解决方案1】:

如果你不能确定结果会小于 9 万亿,我会使用 doubleBigInteger 得到一个错误对你没有多大帮助,因为你仍然需要知道该怎么做.

通过验证您的输入以确保它们在范围内并且如果结果的范围大于long,请使用可以处理此问题的类型,这样一开始就不会出错。

p>

使用 BigInteger 你可以做到

BigInteger a = BigInteger.valueOf(2).multiply(BigInteger.valueOf(Long.MAX_VALUE));
long l = a.longValue();
if (a.compareTo(BigInteger.valueOf(l)) == 0) {
    // ok
} else {
    // error
}

你可以用双打

double d = 2.0 * Long.MAX_VALUE;
long l = (long) Math.max(Long.MIN_VALUE, Math.min(Long.MAX_VALUE, d));
// or as a helper method.
long l = boundedCast(d);

注意:使用 double 而不是 long 可能会导致一些精度损失。

我宁愿首先避免需要错误块。

【讨论】:

  • 问题是,如果超过它,我需要将它修剪到long。也许这有帮助?在我的情况下,出现错误会很有帮助;我可以将整个代码放在 try/catch 块中,如果抛出错误,请将值设置为 Long.MAX_VALUE,因为这就是我所需要的。
  • 如果超过long,则不能修剪。你能做的最好的就是把它设为Long.MAX_VALUE,这不是一个很好的解决方案。
  • @PeterLawrey 我认为上限为Long.MAX_VALUE 是OP 的意思,将其缩减为long
【解决方案2】:

超过 long 的最大值不会引发异常,而是会返回。如果你这样做:

Long.MAX_VALUE + 1

你会注意到结果等同于Long.MIN_VALUE

如果你想让它抛出异常,检查它是否达到最大值并抛出异常

[编辑]

你也可以使用Guava库来检查两个long相加时是否溢出;

long c = LongMath.checkedAdd(a, b);

发生溢出时会抛出异常。

你可以找到javadoc here

【讨论】:

  • “只需做一个 if 检查它是否达到最大值” - 你怎么想的?我不想自己抛出异常,确切地说,我不应该。
  • 你也可以试试这个:long c = LongMath.checkedAdd(a, b);如果对 2 个 long 求和时发生溢出,则会引发异常
  • @DanielA。也许你应该补充一点,你需要Guava library
  • 唉,仅仅为此而建的库并不是我感兴趣的……我不敢相信 Java 会忽略这些东西。正如你所说,当逻辑结果应该是溢出时,“循环回来”对我来说绝对没有意义。可能是一些没人愿意清理的遗留代码......
  • 不同意。这是一个非常深思熟虑且完全合理的要求溢出只取低位。对于初学者来说,任何替代方案都会为 Java 中的每个算术运算带来 大量 性能开销。处理器就是这样做的,就这些事情而言,Java 的行为是相对明智的。
【解决方案3】:

Long 值超过 MAX_VALUE 不会引发任何异常。您需要手动检查和处理此类情况。

尽管@PeterLawrey 建议您应该考虑使用doubleBigInteger

【讨论】:

  • 你如何用双打来做到这一点?已经发布了一个 BigInteger 示例,但是双倍...分配 Long.MAX_VALUE 的双倍值并打印它会给我9.223372036854776E18
猜你喜欢
  • 2017-04-02
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
相关资源
最近更新 更多