2.3 Whole Numbers versus Integer Numbers In Chapter 1, we emphasized how floating-point numbers are not the same as the real numbers of pure mathematics. So far, we've conceded that Java's integer numbers differ from pure math's whole numbers in a major way?athe integer numbers are not infinite. Well, at least we don't have to worry about roundoff errors! But how does the finiteness of the integer types affect integer arithmetic? We first learned how to add and subtract in grade school by using a number line. For example, Figure 2-1 shows that 2 + 3 = 5. Figure 2-1. 2 + 3 = 5 on the number line. Figure 2-2 shows that 6 - 4 = 2. Figure 2-2. 6 - 4 = 2 on the number line. The number line extends infinitely in both the positive and negative directions. But Java's integers are not infinite. When we add 1 to the maximum, or most positive, value of an integer type, the sum "wraps around" to the minimum, or most negative, value of that type. So, instead of an infinite linear number line, we should use a circular arrangement, like a clock face. Figure 2-3 shows how we arrange the values of our pretend nybble integer type. The negative values are in the two's-complement format. Note how the binary values simply increment by 1, from 0000 through 1111 (decimal 0 through §C1), as we move clockwise around the face. In particular, when we add 1 to 7 (binary 0111), the most positive value, the sum wraps around to §C8 (binary 1000), the most negative value. Figure 2-3. Type nybble's values arranged on a clock face. Figure 2-4 shows 2 + 3 = 5 on the clock face. Compare this with Figure 2-1. Figure 2-4. 2 + 3 = 5 on the clock face. Figure 2-5 shows 6 - 4 = 2. Compare this with Figure 2-2. Figure 2-5. 6 - 4 = 2 on the clock face. The virtual machine doesn't consider crossing a boundary between the positive and the negative numbers to be an error, so in nybble arithmetic, 5 + 4 really is -7, as shown in Figure 2-6. Therefore, integer arithmetic does not throw overflow exceptions. Figure 2-6. 5 + 4 = -7 on the clock face. Adding two large positive values of an integer type can give a negative sum. Multiplying large positive values means going around the clock face several times. The product can be either positive or negative. Overflows can be silent killers of integer arithmetic! Program 2 §C1 shows the effects of overflow and of division by zero with int values. See Listing 2-1. Listing 2-1 The effects of integer overflow and division by zero. package numbercruncher.program2_1; /** * PROGRAM 2-1: Integer Overflow * * Show the effects of integer overflow and of division by zero. */ public class IntegerOverflow { public static void main(String args[]) { int big = 2147483645; for (int i = 1; i <= 4; ++i) { System.out.println(big + " + " + i + " = " + (big + i)); } System.out.println(); for (int i = 1; i <= 4; ++i) { System.out.println(big + " * " + i + " = " + (big*i)); } System.out.println(); int dze = big/0; } } Output: 2147483645 + 1 = 2147483646 2147483645 + 2 = 2147483647 2147483645 + 3 = -2147483648 2147483645 + 4 = -2147483647 2147483645 * 1 = 2147483645 2147483645 * 2 = -6 2147483645 * 3 = 2147483639 2147483645 * 4 = -12 java.lang.ArithmeticException: / by zero at numbercruncher.program2_1.IntegerOverflow.main(IntegerOverflow.java:24) Exception in thread "main" |