如何检查Java中的两个数字相乘是否会导致溢出?

我想处理两个数字相乘导致溢出的特殊情况。 代码看起来像这样:

int a = 20;

long b = 30;

// if a or b are big enough, this result will silently overflow

long c = a * b;

这是一个简化版本。 在真实程序中,a和b在运行时的其他地方获取。 我想要实现的是这样的:

long c;

if (a * b will overflow) {

c = Long.MAX_VALUE;

} else {

c = a * b;

}

您如何建议我最好编码?

更新:a和b在我的方案中始终是非负的。

14个解决方案

78 votes

对于int和long,Java 8有Math.multiplyExact,Math.addExact等。 这些在溢出时抛出未经检查的ArithmeticException。

bcoughlan answered 2019-08-26T05:16:03Z

59 votes

如果a和b都是正数,那么您可以使用:

if (a != 0 && b > Long.MAX_VALUE / a) {

// Overflow

}

如果你需要处理正数和负数,那么它就更复杂了:

long maximum = Long.signum(a) == Long.signum(b) ? Long.MAX_VALUE : Long.MIN_VALUE;

if (a != 0 && (b > 0 && b > maximum / a ||

b < 0 && b < maximum / a))

{

// Overflow

}

这是一个小桌子我掀起来检查这个,假装溢出发生在-10或+10:

a = 5 b = 2 2 > 10 / 5

a = 2 b = 5 5 > 10 / 2

a = -5 b = 2 2 > -10 / -5

a = -2 b = 5 5 > -10 / -2

a = 5 b = -2 -2 < -10 / 5

a = 2 b = -5 -5 < -10 / 2

a = -5 b = -2 -2 < 10 / -5

a = -2 b = -5 -5 < 10 / -2

John Kugelman answered 2019-08-26T05:16:43Z

17 votes

有些Java库提供安全的算术运算,可检查长溢出/下溢。 例如,Guava的LongMath.checkedMultiply(long a,long b)返回a和b的乘积,前提是它不溢出,如果a * b在带符号的long算术中溢出,则抛出ArithmeticException。

reprogrammer answered 2019-08-26T05:17:12Z

6 votes

您可以使用java.math.BigInteger来检查结果的大小(避免测试代码):

BigInteger bigC = BigInteger.valueOf(a) * multiply(BigInteger.valueOf(b));

if(bigC.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {

c = Long.MAX_VALUE;

} else {

c = bigC.longValue()

}

Ulf Lindback answered 2019-08-26T05:17:39Z

6 votes

使用对数检查结果的大小。

High Performance Mark answered 2019-08-26T05:18:06Z

4 votes

Java有类似int.MaxValue的东西吗? 如果是,那就试试吧

if (b != 0 && Math.abs(a) > Math.abs(Long.MAX_VALUE / b))

{

// it will overflow

}

编辑:看到有问题的Long.MAX_VALUE

nothrow answered 2019-08-26T05:18:40Z

3 votes

从jruby偷来的

long result = a * b;

if (a != 0 && result / a != b) {

// overflow

}

更新:此代码简短,运行良好; 但是,它失败了a = -1,b = Long.MIN_VALUE。

一个可能的增强:

long result = a * b;

if( (Math.signum(a) * Math.signum(b) != Math.signum(result)) ||

(a != 0L && result / a != b)) {

// overflow

}

请注意,这将捕获一些溢出而不进行任何除法。

rogerdpack answered 2019-08-26T05:19:28Z

2 votes

我不确定为什么没有人在寻找解决方案:

if (Long.MAX_VALUE/a > b) {

// overflows

}

选择一个更大的两个数字。

fastcodejava answered 2019-08-26T05:20:01Z

2 votes

我希望以John Kugelman的答案为基础,而不是通过直接编辑来替换它。 它适用于他的测试用例(MIN_VALUE,MAX_VALUE),因为Long的对称性,这不是两个补码整数的情况。 实际上,Integer。

scala> (java.lang.Integer.MIN_VALUE, java.lang.Integer.MAX_VALUE)

res0: (Int, Int) = (-2147483648,2147483647)

scala> (java.lang.Long.MIN_VALUE, java.lang.Long.MAX_VALUE)

res1: (Long, Long) = (-9223372036854775808,9223372036854775807)

当应用于真实的MIN_VALUE和MAX_VALUE时,John Kugelman的答案会在Long和Integer的任何其他情况下产生溢出情况(由Kyle首先提出)。 以下是解决问题的方法:

long maximum = Long.signum(a) == Long.signum(b) ? Long.MAX_VALUE : Long.MIN_VALUE;

if ((a == -1 && b == Long.MIN_VALUE) ||

(a != -1 && a != 0 && ((b > 0 && b > maximum / a) ||

(b < 0 && b < maximum / a))))

{

// Overflow

}

它不是任何MIN_VALUE和MAX_VALUE的通用解决方案,但它通用于Java的Long和Integer以及任何值a和b。

Jim Pivarski answered 2019-08-26T05:20:47Z

2 votes

这是我能想到的最简单的方法

int a = 20;

long b = 30;

long c = a * b;

if(c / b == a) {

// Everything fine.....no overflow

} else {

// Overflow case, because in case of overflow "c/b" can't equal "a"

}

Naren answered 2019-08-26T05:21:16Z

1 votes

也许:

if(b!= 0 && a * b / b != a) //overflow

不确定这个&#34;解决方案&#34;。

编辑:添加b!= 0。

在你投票之前:a * b / b不会被优化。 这将是编译器错误。 我仍然没有看到可以掩盖溢出错误的情况。

Thomas Jung answered 2019-08-26T05:22:01Z

1 votes

也许这会对你有所帮助:

/**

* @throws ArithmeticException on integer overflow

*/

static long multiply(long a, long b) {

double c = (double) a * b;

long d = a * b;

if ((long) c != d) {

throw new ArithmeticException("int overflow");

} else {

return d;

}

}

dfa answered 2019-08-26T05:22:31Z

1 votes

正如已经指出的那样,Java 8具有Math.xxxExact方法,可以在溢出时抛出异常。

如果您没有将Java 8用于您的项目,您仍然可以&#34;借用&#34; 他们的实现非常紧凑。

以下是第三方网站上这些实现的一些链接,不保证这些实现是否保持有效,但无论如何您应该能够进入JDK源并看看他们如何在Math.addExact类中实现他们的魔力。

Math.addExact[http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Math.java?av=f#882]

Math.addExact[http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Math.java?av=f#805]

等等

StFS answered 2019-08-26T05:23:38Z

-1 votes

c / c ++(long * long):

const int64_ w = (int64_) a * (int64_) b;

if ((long) (w >> sizeof(long) * 8) != (long) w >> (sizeof(long) * 8 - 1))

// overflow

java(int * int,抱歉我在java中找不到int64):

const long w = (long) a * (long) b;

int bits = 32; // int is 32bits in java

if ( (int) (w >> bits) != (int) (w >> (bits - 1))) {

// overflow

}

1.将结果保存为大型(int * int将结果放入long,long * long放入int64)

2.cmp结果&gt;&gt; 位和结果&gt;&gt; (位 - 1)

xuan answered 2019-08-26T05:24:32Z

java输出两个整数的积_如何检查Java中的两个数字相乘是否会导致溢出?相关推荐

  1. 辗转相除法 定义函数fun求两个整数的最大公约数,主函数中输入两个整数,调用该函数得到最大公约数,最后在主函数中输出两个整数的最大公约数和最小公倍数。

    定义函数fun求两个整数的最大公约数,主函数中输入两个整数,调用该函数得到最大公约数,最后在主函数中输出两个整数的最大公约数和最小公倍数. 参考运行截图: 欧几里得算法又称辗转相除法,是指用于计算两个 ...

  2. Java show两个整数加减_怎么样用java编写界面实现两个数的加法运算

    展开全部 import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; ...

  3. python两个时间内的工作日_如何在Python中找到两个日期之间的星期一或任何其他工作日的数目?...

    这是高效的-即使在开始和结束之间有一万天的时间-而且仍然非常灵活(它在sum函数内最多迭代7次):def intervening_weekdays(start, end, inclusive=True ...

  4. c语言,在主函数中输入一个整数,求该整数各位数字的乘积,[求助]求由键盘输入的任意两个整数的积...

    [求助]求由键盘输入的任意两个整数的积 [问题已解决] 我是才接触C的新手,一共才上了4节课,老师就出题了,请高手帮忙看看(如果愿意帮忙改的,请尽量不要改变原来的变量):--------------- ...

  5. 给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

    记录自己坑了又坑的每一天: 原题: 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 div ...

  6. 给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

    给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符.返回被除数 dividend 除以除数 divisor 得到的商.示例 1:输入: ...

  7. 给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。

    给你两个整数,被除数 dividend 和除数 divisor.将两数相除,要求 不使用 乘法.除法和取余运算. 整数除法应该向零截断,也就是截去(truncate)其小数部分.例如,8.345 将被 ...

  8. 程序员面试金典——解题总结: 9.18高难度题 18.5有个内含单词的超大文本文件,给定任意两个单词,找出在这个文件中这两个单词的最短距离

    #include <iostream> #include <stdio.h> #include <vector> #include <string> # ...

  9. java整数的因式分解_如何在Java中找到整数的质数-因式分解

    java整数的因式分解 编程课程中的常见家庭作业/任务之一是关于Prime Factorization. 要求您编写一个程序以找到给定整数的素因子 . 一个数字的素数因子是将精确地除以给定数字的所有素 ...

最新文章

  1. Android之 AndroidManifest xml 文件解析
  2. error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug...
  3. (有图片)汇编工具dosbox下自动mount及切换虚拟目录使用步骤。
  4. 模拟撞击_模玩资讯:EPOCH 汽车撞击测试用模拟假人与实验车辆
  5. GraphQL在SAP Kyma中的广泛应用
  6. ImportError: cannot import name ‘constants‘
  7. 【渝粤教育】 国家开放大学2020年春季 2772家畜环境卫生与设施 参考试题
  8. 《MySQL——38道查询练习(无连接查询)》
  9. angular8多选框实现点击整行任意位置<tr>就可以选中多选框
  10. 多线程的那点儿事(之读写锁)
  11. html滚动选择框代码,如何使用最简单纯Css代码美化checkbox复选框、radios单选框和滑动按钮...
  12. 华为交换机配置syslog发送_配置华为交换机把日志发送到远程centos syslog服务器上...
  13. Linux : 文件处理命令
  14. python中的urllib模块中的方法
  15. 在vue2.0下安装axios
  16. SQL查询语句大全(个人总结)
  17. 测判三极管的口诀 (挑战者)
  18. Vue项目上线后刷新报错404问题(apache,nginx,tomcat)
  19. 【CPU GPU TPU】机器学习扫盲篇
  20. 树莓派之树莓派系统安装

热门文章

  1. oracle-01122,oracle ORA-01200ORA-01110ORA-01122
  2. 占用率_有问有答:任务管理器里面的GPU占用率到底是怎么算的?
  3. 程序员必备技能之单元测试
  4. php 批量修改表格数据,PHP批量修改数据库表前缀教程+代码
  5. oracle数据库十六进制转字符串,Oracle中各种进制相互转换
  6. python中matplotlib出错_Python中使用matplotlib的报错问题
  7. 【3】测试用例设计-因果图
  8. java判断栈中元素数目_Java数据结构与算法-栈和队列
  9. 无所不能java人_无所不能的java
  10. Lesson 3.1 - Python Core Data Types