长+ Long 不大于 Long.MAX_VALUE

发布于 2024-12-29 13:13:01 字数 164 浏览 2 评论 0原文

如果我有作业,

Long c = a + b;

有没有一种简单的方法可以检查 a + b 是否大于/小于 Long.MAX_VALUE/Long.MIN_VALUE

If I have an assignment

Long c = a + b;

Is there an easy way to check that a + b is not bigger/smaller than Long.MAX_VALUE/Long.MIN_VALUE?

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

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

发布评论

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

评论(4

对你再特殊 2025-01-05 13:13:01

使用 Guava,就这么简单

long c = LongMath.checkedAdd(a, b); // throws an ArithmeticException on overflow

,我想,确实非常可读。 (LongMath Javadoc 此处。)

为了公平起见,我会提到 Apache Commons 提供了 ArithmeticUtils.addAndCheck(long, long)

如果你想知道它们是如何工作的,答案是 Guava 的一行位黑客:如果 (a ^ b) (a ^ b) (a ^ b) (a ^ b) (a ^ b) (a ^ b) < 0 | (a^(a+b))>=0。这是基于两个数字的按位异或是非负的技巧,当且仅当它们具有相同的符号。

所以 (a ^ b) <如果 ab 具有不同的符号,则 0 为真,如果是这种情况,则永远不会溢出。或者,如果 (a ^ (a + b)) >= 0,则 a + ba 具有相同的符号,因此它没有溢出并变成负值。

(有关更多类似的技巧,请研究这本可爱的书黑客的乐趣 。)

Apache 使用基于 ab 符号的更复杂的情况。

Using Guava, it's as simple as

long c = LongMath.checkedAdd(a, b); // throws an ArithmeticException on overflow

which is, I'd like to think, very readable indeed. (LongMath Javadoc here.)

For the sake of fairness, I'll mention that Apache Commons provides ArithmeticUtils.addAndCheck(long, long).

If you want to know how they work, well, the answer is one line of bit-hackery for Guava: the result doesn't overflow if (a ^ b) < 0 | (a ^ (a + b)) >= 0. This is based on the trick that the bitwise XOR of two numbers is nonnegative iff they have the same sign.

So (a ^ b) < 0 is true if a and b have different signs, and if that's the case it'll never overflow. Or, if (a ^ (a + b)) >= 0, then a + b has the same sign as a, so it didn't overflow and become negative.

(For more tricks like this, investigate the lovely book Hacker's Delight.)

Apache uses more complicated casework based on the sign of a and b.

酒浓于脸红 2025-01-05 13:13:01

只有当它们具有相同的符号(并且都是 !0)时才会出现问题,否则就不会发生溢出。如果发生溢出,结果的符号将翻转。所以:

long r = a + b;
if ( (a < 0 && b < 0 && r >= 0) ||
     (a > 0 && b > 0 && r <= 0) ) {
    // Overflow occurred
}

It's only an issue if they have the same sign (and are both !0), since otherwise you're safe from overflow. If overflow occurs, the sign of the result will flip. So:

long r = a + b;
if ( (a < 0 && b < 0 && r >= 0) ||
     (a > 0 && b > 0 && r <= 0) ) {
    // Overflow occurred
}
网名女生简单气质 2025-01-05 13:13:01

一种选择是使用 BigInteger 类进行精确计算,然后检查结果是否大于或小于所讨论的值。例如:

if (BigInteger.valueOf(a).add(BigInteger.valueOf(b)).compareTo(BigInteger.valueOf(Long.MAX_VALUE) > 1) {
    /* Overflow occurred. */
} else {
    /* No overflow occurred.
}

希望这有帮助!

One option would be to use the BigInteger class to do the exact computation, then check whether the result is greater than or smaller than the value in question. For example:

if (BigInteger.valueOf(a).add(BigInteger.valueOf(b)).compareTo(BigInteger.valueOf(Long.MAX_VALUE) > 1) {
    /* Overflow occurred. */
} else {
    /* No overflow occurred.
}

Hope this helps!

空气里的味道 2025-01-05 13:13:01

简单的路线:

if(a/2+b/2+(a&b&1)>long.MAX_VALUE/2||a/2+b/2<long.MIN_VALUE/2)...

您只需要希望它不会优化为 (a+b)/2

the simple route:

if(a/2+b/2+(a&b&1)>long.MAX_VALUE/2||a/2+b/2<long.MIN_VALUE/2)...

you just need to hope that it doesn't get optimized to (a+b)/2

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