下面的程序将生成整数对3取余的柱状图,那么,它将打印出什么呢? public class Mod { public static void main(String[ ] args) { final int MODULUS = 3. int[] histogram = new int[MODULUS]. // Iterate over all ints (Idiom from Puzzle 26) int i = Integer.MIN_VALUE. do { histogram[Math.abs(i) % MODULUS] . } while (i != Integer.MAX_VALUE). for (int j = 0. j < MODULUS. j ) System.out.println(histogram[j] " "). } }
该程序首先初始化int数组histogram,其每一个位置都为对3取余的一个数值而准备(0、1和2),所有这三个位置都被初始化为0。然后,该程序在所有232个int数值上遍历变量i,使用的是在谜题26中介绍的惯用法。因为整数取余操作(%)在第一个操作数是负数时,可以返回一个负值,就像在谜题1中所描述的那样,所以该程序在计算i被3整除的余数之前,先取i的绝对值。然后用这个余数来递增数组位置的索引。在循环完成之后,该程序将打印histogram数组中的内容,它的元素表示对3取余得到0、1和2的int数值的个数。 该程序所打印的三个数字应该彼此大致相等,它们加起来应该等于232。如果你想知道怎样计算出它们的精确值,那么你需要有一点数学气质,并仔细阅读下面两段话。否则,你可以跳过这两段话。 该程序打印的三个数字不可能精确地相等,因为它们必须加起来等于232,这个数字不能被3除尽。如果你仔细观察2的连续幂级数对3取余的值,就会发现,它们在1和2之间交替变化:20对3取余是1,21对3取余是2,22对3取余是1,23对3取余是2,以此类推。每一个2的偶次幂对3取余的值都是1,每一个2的奇次幂对3取余的值都是2。因为232对3取余是1,所以该程序所打印的三个数字中有一个将比另外两个大1,但是它是哪一个呢? 该循环依次递增三个数组元素的数值,因此该循环最后递增的那个数值必然是最大的数值,它就是表示Integer.MAX_VALUE或(232-1)对3取余的数值。因为231是2 的奇次幂,所以它对3取余应该得到2,因此(232-1)对3取余将得到1。该程序打印的三个数字中的第二个表示的就是对3取余得到1的int数值的个数,因此,我们期望这个值比第一个和最后一个数值大1。 由此,该程序应该在运行了相当长的时间之后,打印(232/3)的较小值 (232/3)的较大值 (232/3)的较小值,即1431655765 1431655766 1431655765。但是它真的是这么做的吗?不,它几乎立刻就抛出了下面的异常: Exception in thread "main" ArrayIndexOutOfBoundsException: -2 at Mod.main(Mod.java:9)