Minima and maxima
Java provides a set of handy constants indicating the lower and upper bounds of its primitive data types. For example, Integer.MIN_VALUE = -2147483648. Similarly, Double.MAX_VALUE will give you the maximum size a double can have.
A frequent use for these constants is in searching for the smallest or largest value in an array:
public int max(int[] numbers)
{
int max = Integer.MIN_VALUE;
for(int number : numbers)
if (number > max)
max = number;
return max;
}The first value in this array will either be MIN_VALUE itself, or greater than MIN_VALUE and so the result is guaranteed to be correct for all non-empty arrays. For empty arrays the result is undefined, so you might want to add a check to the method
if (numbers.length == 0)
throw new IllegalArgumentException("Numbers array can not be empty");One slight problem
In many ways, these constants are the programming equivalent of plus and minus infinity and it is often safe to use them as such. There are, however, some quirks that make them a little more difficult to work with. Consider the following code
System.out.println(Integer.MIN_VALUE);
System.out.println(-Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);
System.out.println(-Integer.MAX_VALUE);Which returns
-2147483648
-2147483648
2147483647
-2147483647Why? Well MIN_VALUE = -2147483648, so that one's correct. But if you negate that value you get 2147483647+1, which overflows right back into MIN_VALUE. As a result of this, you need to be very careful when passing these values as arguments to a function: if you suspect the function is going to negate the value, you might want to pass -Integer.MAX_VALUE instead of Integer.MIN_VALUE.
A real world example
One situation where this problem arises is MINIMAX using alpha-beta pruning. Wikipedia gives the following pseudo-code (translated from pseudo-pascal into pseudo-java for your benefit :)
public static method alphaBeta(Node node, int depth, int a, int b)
{
if(depth = 0 || node is a terminal node)
return the heuristic value of node
for(Node child : node.children)
{
a = Math.max(a, -alphaBeta(child, depth-1, -b, -a));
if b <= a
break;
}
return a;
}
public static void main(String[] args)
{
// Create nodes
// ...
// Initial call
alphaBeta(origin, depth, -infinity, +infinity);
}This function is called on a graph node that makes recursive calls to its child nodes. Making the initial call as
alphaBeta(origin, depth, Integer.MIN_VALUE, Integer.MAX_VALUE);will cause the first recursive call to invert MAX_VALUE into -MAX_VALUE, and MIN_VALUE into MIN_VALUE: not the desired result! On the other hand
alphaBeta(origin, depth, -Integer.MAX_VALUE, Integer.MAX_VALUE);Will lead to the expected behaviour.
Confusing? I sure think so! If you know a clever way around these situations, please let me know in the comment box below.
Apr 18th, 2010
Comments
No comments yet! Feel free to post some using the form below.
If you wish to add code to your comment you can use code tags, like this: <code class="php">yourCodeHere</code>.
Quite a large number of languages are supported, although I can't guarantee it'll be pretty. Inside the code tags you can use any characters except for the string "</code>".