java 溢出if_Java如何处理整数的下溢和溢出,您将如何检查它?

好吧,就原始整数类型而言,Java根本不处理过流/下溢(对于Float和Double行为是不同的,它将刷新到+/无穷大,就像IEEE-754所要求的那样)。

当添加两个int‘s时,当发生溢出时,您将不会得到任何指示。检查溢出的一个简单方法是使用下一个更大的类型实际执行操作,并检查结果是否仍在源类型的范围内:public int addWithOverflowCheck(int a, int b) {

// the cast of a is required, to make the + work with long precision,

// if we just added (a + b) the addition would use int precision and

// the result would be cast to long afterwards!

long result = ((long) a) + b;

if (result > Integer.MAX_VALUE) {

throw new RuntimeException("Overflow occured");

} else if (result 

throw new RuntimeException("Underflow occured");

}

// at this point we can safely cast back to int, we checked before

// that the value will be withing int's limits

return (int) result;}

您将做什么来代替抛出子句,取决于您的应用程序需求(抛出、刷新到min/max或只记录任何内容)。如果希望在长操作中检测到溢出,则使用BigInteger替代原语。

编辑(2014-05-21):由于这个问题似乎经常被提及,而且我不得不自己解决同样的问题,所以用CPU计算其V标志的相同方法很容易评估溢出状态。

它基本上是一个布尔表达式,它涉及两个操作数的符号以及结果:/**

* Add two int's with overflow detection (r = s + d)

*/public static int add(final int s, final int d) throws ArithmeticException {

int r = s + d;

if (((s & d & ~r) | (~s & ~d & r)) 

throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");

return r;}

在java中,更简单的方法是将表达式(If)应用于整个32位,并使用<0检查结果(这将有效地测试符号位)。这一原则适用于所有整数基元类型,将上述方法中的所有声明更改为LONG使其工作时间很长。

对于较小的类型,由于隐式转换为int(有关详细信息,请参见按位操作的JLS),而不是检查<0,检查需要显式地掩蔽符号位(对于短操作数为0x8000,对于字节操作数为0x80,调整转换和参数声明为接近):/**

* Subtract two short's with overflow detection (r = d - s)

*/public static short sub(final short d, final short s) throws ArithmeticException {

int r = d - s;

if ((((~s & d & ~r) | (s & ~d & r)) & 0x8000) != 0)

throw new ArithmeticException("short overflow sub(" + s + ", " + d + ")");

return (short) r;}

(请注意,上面的示例使用了减法溢出检测)

那么,这些布尔表达式是如何/为什么工作的呢?首先,一些逻辑思维表明溢出可以只如果两个参数的符号相同,则会发生。因为,如果一个参数是否定的,另一个是肯定的,则结果(Add)必接近于零,或者在极端情况下,一个参数是零,与另一个参数相同。因为争论本身不能创建溢出条件,它们的和也不能创建溢出。

那么,如果这两个论点都有相同的符号,会发生什么呢?让我们看一看两者都是正的情况:添加两个参数来创建一个大于MAX_value类型的和,总是会产生一个负值,所以会发生溢出。如果arg 1+arg 2>max_value。现在,可能产生的最大值是max_value+max_value(两个参数的极端情况都是MAX_value)。对于一个字节(例如),这意味着127+127=254。查看通过添加两个正值可以产生的所有值的位表示,一个发现溢出(128到254)的值都有位7集,而所有没有溢出(0到127)的值都清除了位7(最顶部,符号)。这正是表达式的第一个(右)部分检查的内容:if (((s & d & ~r) | (~s & ~d & r)) 

(~s&~d&r)成为事实,只有当,两个操作数(s,d)都是正的,结果(R)是负的(表达式在所有32位上都有效,但是我们感兴趣的唯一位是最上面的(符号)位,它是由<0检查的)。

如果这两个参数都是负数,则它们的和永远不会比任何一个参数之和更接近于零。必接近负无穷远。我们能产生的最极端的值是min_value+min_value,它(同样在字节示例中)显示,对于任何范围内的值(-1到-128),符号位都被设置,而任何可能的溢出值(-129到-256)都清除了符号位。因此,结果的符号再次显示溢出情况。这就是左半部分(s&d&r)检查的情况,即两个参数(s,d)都是负数,结果是肯定的。逻辑在很大程度上等同于正数;所有因添加两个负值而产生的位模式都将清除符号位。当且仅当发生了地下水流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值