How to prevent integer overflow in Java code? [duplicate]

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

Possible Duplicate:
How can I check if multiplying two numbers in Java will cause an overflow?

Suppose I have a Java class method, which uses * and + operations.

 int foo(int a, int b) {   ... // some calculations with + and *  } 

How to make sure that no overflow occurs in foo?

I guess I can either use BigDecimal or replace all + and * with "wrappers" like:

 int sum(int a, int b) {    int c = a + b;    if (a > 0 && b > 0 && c < 0)       throw new MyOverfowException(a, b)    return c; }  int prod(int a, int b) {    int c = a * b;    if (a > 0 && b > 0 && c < 0)       throw new MyOverfowException(a, b)    return c; } 

Are there better ways to make sure that no int overflow occurs in a Java method ?

回答1:

It is a difficult problem from an engineering perspective.

The Secure Coding site recommends:

  • use of preconditions; i.e. range-check the inputs so that overflow is impossible,
  • doing each individual arithmetic operation using the next larger primitive integer type and explicitly checking for overflow, or
  • using BigInteger.

This Dr Dobbs article suggests creating a library of primitive arithmetic methods that do each primitive operation with an explicit overflow check. (You could view this as an implementation of bullet point #2 above.) But the authors go further by suggesting that you use bytecode rewriting to replace arithmetic bytecodes with calls to the equivalent methods which incorporate overflow checks.

Unfortunately, there is no way to enable overflow checking natively in Java. (But the same applies in lots of other languages; e.g. C, C++ ... )



回答2:

One way to check for an overflow is to have the operands promoted to a larger type (of double the original operand bit length) then perform the operation, and then see if the resulting value is too large for the original type, e.g.

int sum(int a, int b) {     long r = (long)a + b;     if (r >>> 32 != 0) {    // no sign extension         throw new MyOverflowException(a, b);     }     return (int)r; } 

If your original type is a long, you'd have to use BigInteger as that larger type.



回答3:

Sum: Check whether b is larger than the difference of the maximum value you can store in int minus the value of a. If a and/or b can be negative, you must (i) be careful not to get an overflow already for the difference check and (ii) perform a similar check for the minimum.

Product: Thats more difficult. I would split the integers into two half-length integers (i.e. if int is 32 bit, split it into two 16 bit numbers using bit-masking and shifting). Then do the multiplication, and then look whether the result fits into 32 bit.

Everything under the condition that you do not want to simply take long for the temporary result.



回答4:

Suppose both a and b are positive or negative, and if the sign of a + b is not equal with the sign of a and b, then overflow happens. You can use this rule to judge whether overflow happens and throw an exception. When you catch this expcetion, you can deal it according to the method metioned in previous answers. Another method is to doing operation using largest range type which will not overflow. You can use long for the operation between Integers.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!