How to violate Comparable interface first provision with integers overflow? - java

java.lang.Comparable#compareTo method states as first provision
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compare-
To(x)) for all x and y. (This implies that x.compareTo(y) must throw
an exception if and only if y.compareTo(x) throws an exception.)
and according Joshua Bloch in Effective Java in item 12
This trick works fine here but should be used with extreme caution.
Don’t use it unless you’re certain the fields in question are
non-negative or, more generally, that the difference between the
lowest and highest possible field values is less than or equal to
Integer.MAX_VALUE (231-1). The reason this trick doesn’t always work
is that a signed 32-bit integer isn’t big enough to hold the
difference between two arbitrary signed 32-bit integers. If i is a
large positive int and j is a large negative int, (i - j) will
overflow and return a negative value. The resulting compareTo method
will return incorrect results for some arguments and violate the first
and second provisions of the compareTo contract. This is not a purely
theoretical problem: it has caused failures in real systems. These
failures can be difficult to debug, as the broken compareTo method
works properly for most input values.
With integers overflow you can violate the first provision and I can't find how, this example shows how the first provision would be violated:
public class ProblemsWithLargeIntegers implements Comparable<ProblemsWithLargeIntegers> {
private int zas;
#Override
public int compareTo(ProblemsWithLargeIntegers o) {
return zas - o.zas;
}
public ProblemsWithLargeIntegers(int zas) {
this.zas = zas;
}
public static void main(String[] args) {
int value1 = ...;
int value2 = ...;
ProblemsWithLargeIntegers d = new ProblemsWithLargeIntegers(value1);
ProblemsWithLargeIntegers e = new ProblemsWithLargeIntegers(value2);
if (!(Math.signum(d.compareTo(e)) == -Math.signum(e.compareTo(d)))){
System.out.println("hey!");
}
}
So I want a value1 and a value2 for getting that? Any idea? Or Joshua was wrong?

Well, this violates the general contract to start with. For example, take value1 = Integer.MIN_VALUE and value2 = 1. That will report that Integer.MIN_VALUE > 1, effectively.
EDIT: Actually, I was wrong - it's easy to violate the first provision:
int value1 = Integer.MIN_VALUE;
int value2 = 0;
You'll get a negative result for both comparisons, because Integer.MIN_VALUE - 0 == 0 - Integer.MIN_VALUE.

Related

Why am I getting the following output to the mentioned "for" loop? [duplicate]

How does Java handle integer underflows and overflows?
Leading on from that, how would you check/test that this is occurring?
If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there.
You can check that beforehand as follows:
public static boolean willAdditionOverflow(int left, int right) {
if (right < 0 && right != Integer.MIN_VALUE) {
return willSubtractionOverflow(left, -right);
} else {
return (~(left ^ right) & (left ^ (left + right))) < 0;
}
}
public static boolean willSubtractionOverflow(int left, int right) {
if (right < 0) {
return willAdditionOverflow(left, -right);
} else {
return ((left ^ right) & (left ^ (left - right))) < 0;
}
}
(you can substitute int by long to perform the same checks for long)
If you think that this may occur more than often, then consider using a datatype or object which can store larger values, e.g. long or maybe java.math.BigInteger. The last one doesn't overflow, practically, the available JVM memory is the limit.
If you happen to be on Java8 already, then you can make use of the new Math#addExact() and Math#subtractExact() methods which will throw an ArithmeticException on overflow.
public static boolean willAdditionOverflow(int left, int right) {
try {
Math.addExact(left, right);
return false;
} catch (ArithmeticException e) {
return true;
}
}
public static boolean willSubtractionOverflow(int left, int right) {
try {
Math.subtractExact(left, right);
return false;
} catch (ArithmeticException e) {
return true;
}
}
The source code can be found here and here respectively.
Of course, you could also just use them right away instead of hiding them in a boolean utility method.
Well, as far as primitive integer types go, Java doesnt handle Over/Underflow at all (for float and double the behaviour is different, it will flush to +/- infinity just as IEEE-754 mandates).
When adding two int's, you will get no indication when an overflow occurs. A simple method to check for overflow is to use the next bigger type to actually perform the operation and check if the result is still in range for the source type:
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 < Integer.MIN_VALUE) {
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;
}
What you would do in place of the throw clauses, depends on your applications requirements (throw, flush to min/max or just log whatever). If you want to detect overflow on long operations, you're out of luck with primitives, use BigInteger instead.
Edit (2014-05-21): Since this question seems to be referred to quite frequently and I had to solve the same problem myself, its quite easy to evaluate the overflow condition by the same method a CPU would calculate its V flag.
Its basically a boolean expression that involves the sign of both operands as well as the result:
/**
* 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)) < 0)
throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");
return r;
}
In java its simpler to apply the expression (in the if) to the entire 32 bits, and check the result using < 0 (this will effectively test the sign bit). The principle works exactly the same for all integer primitive types, changing all declarations in above method to long makes it work for long.
For smaller types, due to the implicit conversion to int (see the JLS for bitwise operations for details), instead of checking < 0, the check needs to mask the sign bit explicitly (0x8000 for short operands, 0x80 for byte operands, adjust casts and parameter declaration appropiately):
/**
* 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;
}
(Note that above example uses the expression need for subtract overflow detection)
So how/why do these boolean expressions work? First, some logical thinking reveals that an overflow can only occur if the signs of both arguments are the same. Because, if one argument is negative and one positive, the result (of add) must be closer to zero, or in the extreme case one argument is zero, the same as the other argument. Since the arguments by themselves can't create an overflow condition, their sum can't create an overflow either.
So what happens if both arguments have the same sign? Lets take a look at the case both are positive: adding two arguments that create a sum larger than the types MAX_VALUE, will always yield a negative value, so an overflow occurs if arg1 + arg2 > MAX_VALUE. Now the maximum value that could result would be MAX_VALUE + MAX_VALUE (the extreme case both arguments are MAX_VALUE). For a byte (example) that would mean 127 + 127 = 254. Looking at the bit representations of all values that can result from adding two positive values, one finds that those that overflow (128 to 254) all have bit 7 set, while all that do not overflow (0 to 127) have bit 7 (topmost, sign) cleared. Thats exactly what the first (right) part of the expression checks:
if (((s & d & ~r) | (~s & ~d & r)) < 0)
(~s & ~d & r) becomes true, only if, both operands (s, d) are positive and the result (r) is negative (the expression works on all 32 bits, but the only bit we're interested in is the topmost (sign) bit, which is checked against by the < 0).
Now if both arguments are negative, their sum can never be closer to zero than any of the arguments, the sum must be closer to minus infinity. The most extreme value we can produce is MIN_VALUE + MIN_VALUE, which (again for byte example) shows that for any in range value (-1 to -128) the sign bit is set, while any possible overflowing value (-129 to -256) has the sign bit cleared. So the sign of the result again reveals the overflow condition. Thats what the left half (s & d & ~r) checks for the case where both arguments (s, d) are negative and a result that is positive. The logic is largely equivalent to the positive case; all bit patterns that can result from adding two negative values will have the sign bit cleared if and only if an underflow occured.
By default, Java's int and long math silently wrap around on overflow and underflow. (Integer operations on other integer types are performed by first promoting the operands to int or long, per JLS 4.2.2.)
As of Java 8, java.lang.Math provides addExact, subtractExact, multiplyExact, incrementExact, decrementExact and negateExact static methods for both int and long arguments that perform the named operation, throwing ArithmeticException on overflow. (There's no divideExact method -- you'll have to check the one special case (MIN_VALUE / -1) yourself.)
As of Java 8, java.lang.Math also provides toIntExact to cast a long to an int, throwing ArithmeticException if the long's value does not fit in an int. This can be useful for e.g. computing the sum of ints using unchecked long math, then using toIntExact to cast to int at the end (but be careful not to let your sum overflow).
If you're still using an older version of Java, Google Guava provides IntMath and LongMath static methods for checked addition, subtraction, multiplication and exponentiation (throwing on overflow). These classes also provide methods to compute factorials and binomial coefficients that return MAX_VALUE on overflow (which is less convenient to check). Guava's primitive utility classes, SignedBytes, UnsignedBytes, Shorts and Ints, provide checkedCast methods for narrowing larger types (throwing IllegalArgumentException on under/overflow, not ArithmeticException), as well as saturatingCast methods that return MIN_VALUE or MAX_VALUE on overflow.
Java doesn't do anything with integer overflow for either int or long primitive types and ignores overflow with positive and negative integers.
This answer first describes the of integer overflow, gives an example of how it can happen, even with intermediate values in expression evaluation, and then gives links to resources that give detailed techniques for preventing and detecting integer overflow.
Integer arithmetic and expressions reslulting in unexpected or undetected overflow are a common programming error. Unexpected or undetected integer overflow is also a well-known exploitable security issue, especially as it affects array, stack and list objects.
Overflow can occur in either a positive or negative direction where the positive or negative value would be beyond the maximum or minimum values for the primitive type in question. Overflow can occur in an intermediate value during expression or operation evaluation and affect the outcome of an expression or operation where the final value would be expected to be within range.
Sometimes negative overflow is mistakenly called underflow. Underflow is what happens when a value would be closer to zero than the representation allows. Underflow occurs in integer arithmetic and is expected. Integer underflow happens when an integer evaluation would be between -1 and 0 or 0 and 1. What would be a fractional result truncates to 0. This is normal and expected with integer arithmetic and not considered an error. However, it can lead to code throwing an exception. One example is an "ArithmeticException: / by zero" exception if the result of integer underflow is used as a divisor in an expression.
Consider the following code:
int bigValue = Integer.MAX_VALUE;
int x = bigValue * 2 / 5;
int y = bigValue / x;
which results in x being assigned 0 and the subsequent evaluation of bigValue / x throws an exception, "ArithmeticException: / by zero" (i.e. divide by zero), instead of y being assigned the value 2.
The expected result for x would be 858,993,458 which is less than the maximum int value of 2,147,483,647. However, the intermediate result from evaluating Integer.MAX_Value * 2, would be 4,294,967,294, which exceeds the maximum int value and is -2 in accordance with 2s complement integer representations. The subsequent evaluation of -2 / 5 evaluates to 0 which gets assigned to x.
Rearranging the expression for computing x to an expression that, when evaluated, divides before multiplying, the following code:
int bigValue = Integer.MAX_VALUE;
int x = bigValue / 5 * 2;
int y = bigValue / x;
results in x being assigned 858,993,458 and y being assigned 2, which is expected.
The intermediate result from bigValue / 5 is 429,496,729 which does not exceed the maximum value for an int. Subsequent evaluation of 429,496,729 * 2 doesn't exceed the maximum value for an int and the expected result gets assigned to x. The evaluation for y then does not divide by zero. The evaluations for x and y work as expected.
Java integer values are stored as and behave in accordance with 2s complement signed integer representations. When a resulting value would be larger or smaller than the maximum or minimum integer values, a 2's complement integer value results instead. In situations not expressly designed to use 2s complement behavior, which is most ordinary integer arithmetic situations, the resulting 2s complement value will cause a programming logic or computation error as was shown in the example above. An excellent Wikipedia article describes 2s compliment binary integers here: Two's complement - Wikipedia
There are techniques for avoiding unintentional integer overflow. Techinques may be categorized as using pre-condition testing, upcasting and BigInteger.
Pre-condition testing comprises examining the values going into an arithmetic operation or expression to ensure that an overflow won't occur with those values. Programming and design will need to create testing that ensures input values won't cause overflow and then determine what to do if input values occur that will cause overflow.
Upcasting comprises using a larger primitive type to perform the arithmetic operation or expression and then determining if the resulting value is beyond the maximum or minimum values for an integer. Even with upcasting, it is still possible that the value or some intermediate value in an operation or expression will be beyond the maximum or minimum values for the upcast type and cause overflow, which will also not be detected and will cause unexpected and undesired results. Through analysis or pre-conditions, it may be possible to prevent overflow with upcasting when prevention without upcasting is not possible or practical. If the integers in question are already long primitive types, then upcasting is not possible with primitive types in Java.
The BigInteger technique comprises using BigInteger for the arithmetic operation or expression using library methods that use BigInteger. BigInteger does not overflow. It will use all available memory, if necessary. Its arithmetic methods are normally only slightly less efficient than integer operations. It is still possible that a result using BigInteger may be beyond the maximum or minimum values for an integer, however, overflow will not occur in the arithmetic leading to the result. Programming and design will still need to determine what to do if a BigInteger result is beyond the maximum or minimum values for the desired primitive result type, e.g., int or long.
The Carnegie Mellon Software Engineering Institute's CERT program and Oracle have created a set of standards for secure Java programming. Included in the standards are techniques for preventing and detecting integer overflow. The standard is published as a freely accessible online resource here: The CERT Oracle Secure Coding Standard for Java
The standard's section that describes and contains practical examples of coding techniques for preventing or detecting integer overflow is here: NUM00-J. Detect or prevent integer overflow
Book form and PDF form of The CERT Oracle Secure Coding Standard for Java are also available.
Having just kinda run into this problem myself, here's my solution (for both multiplication and addition):
static boolean wouldOverflowOccurwhenMultiplying(int a, int b) {
// If either a or b are Integer.MIN_VALUE, then multiplying by anything other than 0 or 1 will result in overflow
if (a == 0 || b == 0) {
return false;
} else if (a > 0 && b > 0) { // both positive, non zero
return a > Integer.MAX_VALUE / b;
} else if (b < 0 && a < 0) { // both negative, non zero
return a < Integer.MAX_VALUE / b;
} else { // exactly one of a,b is negative and one is positive, neither are zero
if (b > 0) { // this last if statements protects against Integer.MIN_VALUE / -1, which in itself causes overflow.
return a < Integer.MIN_VALUE / b;
} else { // a > 0
return b < Integer.MIN_VALUE / a;
}
}
}
boolean wouldOverflowOccurWhenAdding(int a, int b) {
if (a > 0 && b > 0) {
return a > Integer.MAX_VALUE - b;
} else if (a < 0 && b < 0) {
return a < Integer.MIN_VALUE - b;
}
return false;
}
feel free to correct if wrong or if can be simplified. I've done some testing with the multiplication method, mostly edge cases, but it could still be wrong.
There are libraries that provide safe arithmetic operations, which check integer overflow/underflow . For example, Guava's IntMath.checkedAdd(int a, int b) returns the sum of a and b, provided it does not overflow, and throws ArithmeticException if a + b overflows in signed int arithmetic.
It wraps around.
e.g:
public class Test {
public static void main(String[] args) {
int i = Integer.MAX_VALUE;
int j = Integer.MIN_VALUE;
System.out.println(i+1);
System.out.println(j-1);
}
}
prints
-2147483648
2147483647
Since java8 the java.lang.Math package has methods like addExact() and multiplyExact() which will throw an ArithmeticException when an overflow occurs.
I think you should use something like this and it is called Upcasting:
public int multiplyBy2(int x) throws ArithmeticException {
long result = 2 * (long) x;
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE){
throw new ArithmeticException("Integer overflow");
}
return (int) result;
}
You can read further here:
Detect or prevent integer overflow
It is quite reliable source.
It doesn't do anything -- the under/overflow just happens.
A "-1" that is the result of a computation that overflowed is no different from the "-1" that resulted from any other information. So you can't tell via some status or by inspecting just a value whether it's overflowed.
But you can be smart about your computations in order to avoid overflow, if it matters, or at least know when it will happen. What's your situation?
static final int safeAdd(int left, int right)
throws ArithmeticException {
if (right > 0 ? left > Integer.MAX_VALUE - right
: left < Integer.MIN_VALUE - right) {
throw new ArithmeticException("Integer overflow");
}
return left + right;
}
static final int safeSubtract(int left, int right)
throws ArithmeticException {
if (right > 0 ? left < Integer.MIN_VALUE + right
: left > Integer.MAX_VALUE + right) {
throw new ArithmeticException("Integer overflow");
}
return left - right;
}
static final int safeMultiply(int left, int right)
throws ArithmeticException {
if (right > 0 ? left > Integer.MAX_VALUE/right
|| left < Integer.MIN_VALUE/right
: (right < -1 ? left > Integer.MIN_VALUE/right
|| left < Integer.MAX_VALUE/right
: right == -1
&& left == Integer.MIN_VALUE) ) {
throw new ArithmeticException("Integer overflow");
}
return left * right;
}
static final int safeDivide(int left, int right)
throws ArithmeticException {
if ((left == Integer.MIN_VALUE) && (right == -1)) {
throw new ArithmeticException("Integer overflow");
}
return left / right;
}
static final int safeNegate(int a) throws ArithmeticException {
if (a == Integer.MIN_VALUE) {
throw new ArithmeticException("Integer overflow");
}
return -a;
}
static final int safeAbs(int a) throws ArithmeticException {
if (a == Integer.MIN_VALUE) {
throw new ArithmeticException("Integer overflow");
}
return Math.abs(a);
}
There is one case, that is not mentioned above:
int res = 1;
while (res != 0) {
res *= 2;
}
System.out.println(res);
will produce:
0
This case was discussed here:
Integer overflow produces Zero.
I think this should be fine.
static boolean addWillOverFlow(int a, int b) {
return (Integer.signum(a) == Integer.signum(b)) &&
(Integer.signum(a) != Integer.signum(a+b));
}

JAVA integer overflow intrigue

The 1st for loop in the below code does not find the maximum correctly due to an overflow. However, the 2nd for loop does. I used godbolt.com to look at the byte codes for this program which showed that to determine which number is greater the 1st for loop uses an isub and the 2nd for loop uses an if_icmple. Makes sense. However, why is the if_icmple able to successfully do this comparison since it too at some point must do a subtraction (which I would expect to produce an overflow)?
public class Overflow {
public static void main(String[] args) {
int[] nums = {3,-2147483648, 5, 7, 27, 9};
int curMax = nums[0];
for (int num : nums) {
int diff = curMax - num;
if (diff < 0) {
curMax = num;
}
}
System.out.println("1) max is " + curMax);
curMax = nums[0];
for (int num : nums) {
if (num > curMax) {
curMax = num;
}
}
System.out.println("2) max is " + curMax);
}
}
The output is
max is -2147483648
max is 27
Let's say that comparison is implemented using subtraction. Contrary to various other opinions here, I'd say that is highly likely. Eg cmp on x86 is just a subtraction that does not update its destination register, only the flags. Various other (but maybe not all) processors that have a flags register also work that way. In the rest of this answer I'll use x86 as a representative processor for examples.
However, there is an incorrect assumption made implicitly by your code: a comparison is not equivalent to a subtraction followed by checking the sign, it is equivalent to a subtraction followed by checking some combination of the Zero, Sign, and Overflow flags. For example, if you implement if (num > curMax) using some cmp followed by jle (to skip the body of the if when the condition is false), then jle does this:
Jump short if less or equal (ZF=1 or SF≠ OF).
Expressing the condition SF≠ OF directly in Java is not so easy. But the JVM itself has no such problem, it can use a comparison (or, equivalently, subtraction) followed by exactly the right kind of conditional jump.
There are some less-fortunate processors that do not have such as full set of conditional jumps as x86 has, but even in that case, the JVM has a lot more options than you do.
The option that the JVM does not have though, is implementing comparison incorrectly.
However, why is the if_icmple able to successfully do this comparison since it too at some point must do a subtraction (which I would expect to produce an overflow)?
It doesn't need to do a subtraction. It just needs to do a comparison. Comparisons don't have to involve subtraction, certainly not in the CPU.
Of course, we can also take alternate steps to deal with overflow. Here is one simple approach:
int cmp(int a, int b) {
boolean aNeg = (a >>> 31) != 0;
boolean bNeg = (b >>> 31) != 0;
if (aNeg != bNeg) {
return aNeg ? -1 : 1;
}
int diff = a - b; // subtracting two numbers with the same sign can't overflow
return (diff == 0) ? 0 : (diff < 0) ? -1 : 1;
}
All Java has to do is compile if_icmple to something like this, or whatever other instruction is appropriate on the target CPU. Using bytecode means Java can leave that up to the runtime to get right for the target CPU, whatever's fastest in such an environment -- using the overflow bit, doing something like this, whatever.

Java - Adding multiple longs overflow/underflow check [duplicate]

How does Java handle integer underflows and overflows?
Leading on from that, how would you check/test that this is occurring?
If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there.
You can check that beforehand as follows:
public static boolean willAdditionOverflow(int left, int right) {
if (right < 0 && right != Integer.MIN_VALUE) {
return willSubtractionOverflow(left, -right);
} else {
return (~(left ^ right) & (left ^ (left + right))) < 0;
}
}
public static boolean willSubtractionOverflow(int left, int right) {
if (right < 0) {
return willAdditionOverflow(left, -right);
} else {
return ((left ^ right) & (left ^ (left - right))) < 0;
}
}
(you can substitute int by long to perform the same checks for long)
If you think that this may occur more than often, then consider using a datatype or object which can store larger values, e.g. long or maybe java.math.BigInteger. The last one doesn't overflow, practically, the available JVM memory is the limit.
If you happen to be on Java8 already, then you can make use of the new Math#addExact() and Math#subtractExact() methods which will throw an ArithmeticException on overflow.
public static boolean willAdditionOverflow(int left, int right) {
try {
Math.addExact(left, right);
return false;
} catch (ArithmeticException e) {
return true;
}
}
public static boolean willSubtractionOverflow(int left, int right) {
try {
Math.subtractExact(left, right);
return false;
} catch (ArithmeticException e) {
return true;
}
}
The source code can be found here and here respectively.
Of course, you could also just use them right away instead of hiding them in a boolean utility method.
Well, as far as primitive integer types go, Java doesnt handle Over/Underflow at all (for float and double the behaviour is different, it will flush to +/- infinity just as IEEE-754 mandates).
When adding two int's, you will get no indication when an overflow occurs. A simple method to check for overflow is to use the next bigger type to actually perform the operation and check if the result is still in range for the source type:
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 < Integer.MIN_VALUE) {
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;
}
What you would do in place of the throw clauses, depends on your applications requirements (throw, flush to min/max or just log whatever). If you want to detect overflow on long operations, you're out of luck with primitives, use BigInteger instead.
Edit (2014-05-21): Since this question seems to be referred to quite frequently and I had to solve the same problem myself, its quite easy to evaluate the overflow condition by the same method a CPU would calculate its V flag.
Its basically a boolean expression that involves the sign of both operands as well as the result:
/**
* 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)) < 0)
throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");
return r;
}
In java its simpler to apply the expression (in the if) to the entire 32 bits, and check the result using < 0 (this will effectively test the sign bit). The principle works exactly the same for all integer primitive types, changing all declarations in above method to long makes it work for long.
For smaller types, due to the implicit conversion to int (see the JLS for bitwise operations for details), instead of checking < 0, the check needs to mask the sign bit explicitly (0x8000 for short operands, 0x80 for byte operands, adjust casts and parameter declaration appropiately):
/**
* 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;
}
(Note that above example uses the expression need for subtract overflow detection)
So how/why do these boolean expressions work? First, some logical thinking reveals that an overflow can only occur if the signs of both arguments are the same. Because, if one argument is negative and one positive, the result (of add) must be closer to zero, or in the extreme case one argument is zero, the same as the other argument. Since the arguments by themselves can't create an overflow condition, their sum can't create an overflow either.
So what happens if both arguments have the same sign? Lets take a look at the case both are positive: adding two arguments that create a sum larger than the types MAX_VALUE, will always yield a negative value, so an overflow occurs if arg1 + arg2 > MAX_VALUE. Now the maximum value that could result would be MAX_VALUE + MAX_VALUE (the extreme case both arguments are MAX_VALUE). For a byte (example) that would mean 127 + 127 = 254. Looking at the bit representations of all values that can result from adding two positive values, one finds that those that overflow (128 to 254) all have bit 7 set, while all that do not overflow (0 to 127) have bit 7 (topmost, sign) cleared. Thats exactly what the first (right) part of the expression checks:
if (((s & d & ~r) | (~s & ~d & r)) < 0)
(~s & ~d & r) becomes true, only if, both operands (s, d) are positive and the result (r) is negative (the expression works on all 32 bits, but the only bit we're interested in is the topmost (sign) bit, which is checked against by the < 0).
Now if both arguments are negative, their sum can never be closer to zero than any of the arguments, the sum must be closer to minus infinity. The most extreme value we can produce is MIN_VALUE + MIN_VALUE, which (again for byte example) shows that for any in range value (-1 to -128) the sign bit is set, while any possible overflowing value (-129 to -256) has the sign bit cleared. So the sign of the result again reveals the overflow condition. Thats what the left half (s & d & ~r) checks for the case where both arguments (s, d) are negative and a result that is positive. The logic is largely equivalent to the positive case; all bit patterns that can result from adding two negative values will have the sign bit cleared if and only if an underflow occured.
By default, Java's int and long math silently wrap around on overflow and underflow. (Integer operations on other integer types are performed by first promoting the operands to int or long, per JLS 4.2.2.)
As of Java 8, java.lang.Math provides addExact, subtractExact, multiplyExact, incrementExact, decrementExact and negateExact static methods for both int and long arguments that perform the named operation, throwing ArithmeticException on overflow. (There's no divideExact method -- you'll have to check the one special case (MIN_VALUE / -1) yourself.)
As of Java 8, java.lang.Math also provides toIntExact to cast a long to an int, throwing ArithmeticException if the long's value does not fit in an int. This can be useful for e.g. computing the sum of ints using unchecked long math, then using toIntExact to cast to int at the end (but be careful not to let your sum overflow).
If you're still using an older version of Java, Google Guava provides IntMath and LongMath static methods for checked addition, subtraction, multiplication and exponentiation (throwing on overflow). These classes also provide methods to compute factorials and binomial coefficients that return MAX_VALUE on overflow (which is less convenient to check). Guava's primitive utility classes, SignedBytes, UnsignedBytes, Shorts and Ints, provide checkedCast methods for narrowing larger types (throwing IllegalArgumentException on under/overflow, not ArithmeticException), as well as saturatingCast methods that return MIN_VALUE or MAX_VALUE on overflow.
Java doesn't do anything with integer overflow for either int or long primitive types and ignores overflow with positive and negative integers.
This answer first describes the of integer overflow, gives an example of how it can happen, even with intermediate values in expression evaluation, and then gives links to resources that give detailed techniques for preventing and detecting integer overflow.
Integer arithmetic and expressions reslulting in unexpected or undetected overflow are a common programming error. Unexpected or undetected integer overflow is also a well-known exploitable security issue, especially as it affects array, stack and list objects.
Overflow can occur in either a positive or negative direction where the positive or negative value would be beyond the maximum or minimum values for the primitive type in question. Overflow can occur in an intermediate value during expression or operation evaluation and affect the outcome of an expression or operation where the final value would be expected to be within range.
Sometimes negative overflow is mistakenly called underflow. Underflow is what happens when a value would be closer to zero than the representation allows. Underflow occurs in integer arithmetic and is expected. Integer underflow happens when an integer evaluation would be between -1 and 0 or 0 and 1. What would be a fractional result truncates to 0. This is normal and expected with integer arithmetic and not considered an error. However, it can lead to code throwing an exception. One example is an "ArithmeticException: / by zero" exception if the result of integer underflow is used as a divisor in an expression.
Consider the following code:
int bigValue = Integer.MAX_VALUE;
int x = bigValue * 2 / 5;
int y = bigValue / x;
which results in x being assigned 0 and the subsequent evaluation of bigValue / x throws an exception, "ArithmeticException: / by zero" (i.e. divide by zero), instead of y being assigned the value 2.
The expected result for x would be 858,993,458 which is less than the maximum int value of 2,147,483,647. However, the intermediate result from evaluating Integer.MAX_Value * 2, would be 4,294,967,294, which exceeds the maximum int value and is -2 in accordance with 2s complement integer representations. The subsequent evaluation of -2 / 5 evaluates to 0 which gets assigned to x.
Rearranging the expression for computing x to an expression that, when evaluated, divides before multiplying, the following code:
int bigValue = Integer.MAX_VALUE;
int x = bigValue / 5 * 2;
int y = bigValue / x;
results in x being assigned 858,993,458 and y being assigned 2, which is expected.
The intermediate result from bigValue / 5 is 429,496,729 which does not exceed the maximum value for an int. Subsequent evaluation of 429,496,729 * 2 doesn't exceed the maximum value for an int and the expected result gets assigned to x. The evaluation for y then does not divide by zero. The evaluations for x and y work as expected.
Java integer values are stored as and behave in accordance with 2s complement signed integer representations. When a resulting value would be larger or smaller than the maximum or minimum integer values, a 2's complement integer value results instead. In situations not expressly designed to use 2s complement behavior, which is most ordinary integer arithmetic situations, the resulting 2s complement value will cause a programming logic or computation error as was shown in the example above. An excellent Wikipedia article describes 2s compliment binary integers here: Two's complement - Wikipedia
There are techniques for avoiding unintentional integer overflow. Techinques may be categorized as using pre-condition testing, upcasting and BigInteger.
Pre-condition testing comprises examining the values going into an arithmetic operation or expression to ensure that an overflow won't occur with those values. Programming and design will need to create testing that ensures input values won't cause overflow and then determine what to do if input values occur that will cause overflow.
Upcasting comprises using a larger primitive type to perform the arithmetic operation or expression and then determining if the resulting value is beyond the maximum or minimum values for an integer. Even with upcasting, it is still possible that the value or some intermediate value in an operation or expression will be beyond the maximum or minimum values for the upcast type and cause overflow, which will also not be detected and will cause unexpected and undesired results. Through analysis or pre-conditions, it may be possible to prevent overflow with upcasting when prevention without upcasting is not possible or practical. If the integers in question are already long primitive types, then upcasting is not possible with primitive types in Java.
The BigInteger technique comprises using BigInteger for the arithmetic operation or expression using library methods that use BigInteger. BigInteger does not overflow. It will use all available memory, if necessary. Its arithmetic methods are normally only slightly less efficient than integer operations. It is still possible that a result using BigInteger may be beyond the maximum or minimum values for an integer, however, overflow will not occur in the arithmetic leading to the result. Programming and design will still need to determine what to do if a BigInteger result is beyond the maximum or minimum values for the desired primitive result type, e.g., int or long.
The Carnegie Mellon Software Engineering Institute's CERT program and Oracle have created a set of standards for secure Java programming. Included in the standards are techniques for preventing and detecting integer overflow. The standard is published as a freely accessible online resource here: The CERT Oracle Secure Coding Standard for Java
The standard's section that describes and contains practical examples of coding techniques for preventing or detecting integer overflow is here: NUM00-J. Detect or prevent integer overflow
Book form and PDF form of The CERT Oracle Secure Coding Standard for Java are also available.
Having just kinda run into this problem myself, here's my solution (for both multiplication and addition):
static boolean wouldOverflowOccurwhenMultiplying(int a, int b) {
// If either a or b are Integer.MIN_VALUE, then multiplying by anything other than 0 or 1 will result in overflow
if (a == 0 || b == 0) {
return false;
} else if (a > 0 && b > 0) { // both positive, non zero
return a > Integer.MAX_VALUE / b;
} else if (b < 0 && a < 0) { // both negative, non zero
return a < Integer.MAX_VALUE / b;
} else { // exactly one of a,b is negative and one is positive, neither are zero
if (b > 0) { // this last if statements protects against Integer.MIN_VALUE / -1, which in itself causes overflow.
return a < Integer.MIN_VALUE / b;
} else { // a > 0
return b < Integer.MIN_VALUE / a;
}
}
}
boolean wouldOverflowOccurWhenAdding(int a, int b) {
if (a > 0 && b > 0) {
return a > Integer.MAX_VALUE - b;
} else if (a < 0 && b < 0) {
return a < Integer.MIN_VALUE - b;
}
return false;
}
feel free to correct if wrong or if can be simplified. I've done some testing with the multiplication method, mostly edge cases, but it could still be wrong.
There are libraries that provide safe arithmetic operations, which check integer overflow/underflow . For example, Guava's IntMath.checkedAdd(int a, int b) returns the sum of a and b, provided it does not overflow, and throws ArithmeticException if a + b overflows in signed int arithmetic.
It wraps around.
e.g:
public class Test {
public static void main(String[] args) {
int i = Integer.MAX_VALUE;
int j = Integer.MIN_VALUE;
System.out.println(i+1);
System.out.println(j-1);
}
}
prints
-2147483648
2147483647
Since java8 the java.lang.Math package has methods like addExact() and multiplyExact() which will throw an ArithmeticException when an overflow occurs.
I think you should use something like this and it is called Upcasting:
public int multiplyBy2(int x) throws ArithmeticException {
long result = 2 * (long) x;
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE){
throw new ArithmeticException("Integer overflow");
}
return (int) result;
}
You can read further here:
Detect or prevent integer overflow
It is quite reliable source.
It doesn't do anything -- the under/overflow just happens.
A "-1" that is the result of a computation that overflowed is no different from the "-1" that resulted from any other information. So you can't tell via some status or by inspecting just a value whether it's overflowed.
But you can be smart about your computations in order to avoid overflow, if it matters, or at least know when it will happen. What's your situation?
static final int safeAdd(int left, int right)
throws ArithmeticException {
if (right > 0 ? left > Integer.MAX_VALUE - right
: left < Integer.MIN_VALUE - right) {
throw new ArithmeticException("Integer overflow");
}
return left + right;
}
static final int safeSubtract(int left, int right)
throws ArithmeticException {
if (right > 0 ? left < Integer.MIN_VALUE + right
: left > Integer.MAX_VALUE + right) {
throw new ArithmeticException("Integer overflow");
}
return left - right;
}
static final int safeMultiply(int left, int right)
throws ArithmeticException {
if (right > 0 ? left > Integer.MAX_VALUE/right
|| left < Integer.MIN_VALUE/right
: (right < -1 ? left > Integer.MIN_VALUE/right
|| left < Integer.MAX_VALUE/right
: right == -1
&& left == Integer.MIN_VALUE) ) {
throw new ArithmeticException("Integer overflow");
}
return left * right;
}
static final int safeDivide(int left, int right)
throws ArithmeticException {
if ((left == Integer.MIN_VALUE) && (right == -1)) {
throw new ArithmeticException("Integer overflow");
}
return left / right;
}
static final int safeNegate(int a) throws ArithmeticException {
if (a == Integer.MIN_VALUE) {
throw new ArithmeticException("Integer overflow");
}
return -a;
}
static final int safeAbs(int a) throws ArithmeticException {
if (a == Integer.MIN_VALUE) {
throw new ArithmeticException("Integer overflow");
}
return Math.abs(a);
}
There is one case, that is not mentioned above:
int res = 1;
while (res != 0) {
res *= 2;
}
System.out.println(res);
will produce:
0
This case was discussed here:
Integer overflow produces Zero.
I think this should be fine.
static boolean addWillOverFlow(int a, int b) {
return (Integer.signum(a) == Integer.signum(b)) &&
(Integer.signum(a) != Integer.signum(a+b));
}

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

This question already has answers here:
Closed 10 years ago.
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 ?
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.
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++ ... )
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.
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.

Java Comparable return value, does it have to be exactly 1, -1 or 0?

This might be a trivial question, but I have not found anything about it, so here goes:
When implementing the Comparable interface, we are supposed to define the method compareTo(), so that the following is true according to the documentation:
sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.
The relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.
x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.
Now, the part that gets confusing is the return value, that is specified as follows:
Returns a negative integer, zero, or a positive integer as this object
is less than, equal to, or greater than the specified object.
It seems that most implementations return 1, -1 or 0, even though it is not mentioned as a requirement that the return value is limited in this way.
The following code thus works for Sorting a list (using Collections.sort()) containing instances of a class, Foo:
public int compareTo(Foo other){
return this.value > other.value? 1 : this.value < other.value ? -1 : 0;
}
This however do not:
public int compareTo(Foo other){
return (int)(this.value - other.value);
}
Where value is a long, and the difference between the values do not exceed Integer.MAX_VALUE.
Am I missing something here, or is the return value required to be exactly 1, -1 or 0, contradictory to the documentation?
Update: Thanks for all your answers, but it seems that the human factor was to blame here. I mentioned that the calculated difference was less than Integer.MAX_VALUE, which should mean that there is no overflow, but my calculations were wrong, so I did actually get overflow, which caused the strange results.
The contract was so flexible to allow this.value - other.value idioms (which later turned out to be incorrect due to integer overflow). But in some cases it is still valueable, like str.length() - str2.length(). It is unlikely impossible that string or array size comparison will overflow since the minimum length is 0 and the maximum is Integer.MAX_VALUE (0 - Integer.MAX_VALUE is still greater than Integer.MIN_VALUE) so it is convenient when you need to sort by length/size.
Also comparing to 0 (greater-than/less-than) is often faster/genrates smaller bytecode/assembly than comparing to 1/-1, so why limit the users? You are absolutely free to use any positive/negative value.
Nope, you can return any integer you want. What exactly is the error you are getting?
Please test the following class:
public static void main(String[] args) {
final ToSort sort0 = new ToSort(-100);
final ToSort sort1 = new ToSort(1);
final ToSort sort2 = new ToSort(100);
List<ToSort> elements = new ArrayList<ToSort>(){{add(sort2); add(sort1); add(sort0);}};
System.out.println("Unsorted:" + elements.toString());
Collections.sort(elements);
System.out.println("Sorted:" + elements.toString());
}
static class ToSort implements Comparable{
long value;
public ToSort(long value){
this.value = value;
}
#Override
public int compareTo(Object other) {
return (int) (this.value - ((ToSort)other).value);
}
public String toString(){
return ""+value;
}
}
I get the following output:
run:
Unsorted:[100, 1, -100]
Sorted:[-100, 1, 100]
BUILD SUCCESSFUL (total time: 0 seconds)
You might want to add a breakpoint in your compareTo method and debug to check if you are running what you are expecting.
Javadocs also say:
In the foregoing description, the notation sgn(expression) designates the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.
EDIT:
Yes, i misunderstood. you are right.

Categories

Resources