Java 如何检测32位int上的整数溢出?
我知道这样的话题被问了好几次,但我的问题是关于整型32位的溢出。例如:Java 如何检测32位int上的整数溢出?,java,integer,bit-manipulation,integer-overflow,integer-arithmetic,Java,Integer,Bit Manipulation,Integer Overflow,Integer Arithmetic,我知道这样的话题被问了好几次,但我的问题是关于整型32位的溢出。例如: 11111111111111111111111111111111 + 00000000000000000000000000000001 = 00000000000000000000000000000000 //overflow! 我发现有类似的问题,但是算法并不完美 11111111111111111111111111111111 + 00000000000000000000000000000000
11111111111111111111111111111111 +
00000000000000000000000000000001 =
00000000000000000000000000000000 //overflow!
我发现有类似的问题,但是算法并不完美
11111111111111111111111111111111 +
00000000000000000000000000000000 =
00000000000000000000000000000000 //overflow!
有什么简单、快速、安全的方法来检查这个问题吗?longtest=(long)x+y;
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
// Overflow!
如果(测试>整数.MAX|u值|测试<整数.MIN_值)
//溢出!
溢出可以通过两个操作数的最高有效位的逻辑表达式和(截断的)结果(我从MC68030手册中获取了逻辑表达式)来检测:
/**
*添加两个带溢出检测的整数(r=s+d)
*/
公共静态int add(int s,int d)抛出算术异常{
int r=s+d;
如果(((s&d&r)|(~s&d&r))<0)
抛出新的算术异常(“整数溢出加法(“+s+”,“+d+”);
返回r;
}
Math.addExact
溢出时引发异常
由于Java 8,类中有一组方法:
int x = 2_000_000_000;
int y = 1_000_000_000;
try {
int result = Math.addExact(x, y);
System.out.println("The proper result is " + result);
} catch(ArithmeticException e) {
System.out.println("Sorry, " + e);
}
看这个
抱歉,java.lang.arithmetricException:整数溢出
我能想到的最直观的方法是:将总和(或差值)计算为
long
,然后将该总和转换为int
,查看其值是否发生了变化
long longSum = (long) a + b;
int sum = (int) longSum;
if (sum == longSum) {
// sum contains the correct result
} else {
// overflow/underflow
}
请记住,在现代64位处理器上,使用long
s的效率不低于使用int
s的效率(事实可能恰恰相反)。因此,如果您可以选择检查溢出还是使用long
s,请选择后者。尝试以下方法:
boolean isOverflow(int left, int right) {
return right > 0
? Integer.MAX_VALUE - right < left
: Integer.MIN_VALUE - right > left;
}
boolean isOverflow(int-left,int-right){
返回右侧>0
?整数.MAX_值-右<左
:Integer.MIN_值-右>左;
}
From:BTW,Java int始终是32位的(无论给定JVM在什么架构上运行[):“默认情况下,int数据类型是一个32位带符号的2的补码整数,最小值为-231,最大值为231-1”().因此,这里的32位规范似乎有点不相关/没有意义。x&y是否被假定为long本身?如果它们是int,我认为这不会起作用(因为溢出在长强制转换之前不会被检测到);我对吗?你错了。x在加法之前被强制转换为long(优先级).long+int int将int转换为long,最终得到long+long。因此,整个操作以64位精度完成。啊,好的,因此强制转换优先于加法运算符。谢谢!不适用于乘法。
isOverflow中的溢出(-47483648,-100000000)未检测到
。这实际上不是溢出:)Java 8的addExact
编码为if(((s^r)和(d^r))<0)
。
boolean isOverflow(int left, int right) {
return right > 0
? Integer.MAX_VALUE - right < left
: Integer.MIN_VALUE - right > left;
}