IT Notes‎ > ‎Java‎ > ‎Java Language‎ > ‎《Java 解惑》笔记‎ > ‎

Puzzle 35: Minute by Minute

一个由魔术数字引发的错误


问题:已知一小时的毫秒数和每分钟的毫秒数,通过使用循环结构,求一小时有多少分钟。
按:就这个问题的所求目标来说,使用循环确实有点BT,但本 Puzzle 要说明魔术数字引发的血案,偏偏需要这么做。

用到的代码如下:
public class Clock {

    public static void main(String[] args) {
        int minutes = 0;
        for (int ms = 0; ms < 60 * 60 * 1000; ms++) {
            if (ms % 60 * 1000 == 0) {
                minutes++;
            }
        }
        System.out.println(minutes);
    }
}


输出的结果是60吧,错,是60000,直接 ft 了。

ms % 60 * 1000 这以表达式的原因,它等价于 (ms % 60) * 1000。改成下面的形式就好了:
ms % (60 * 1000)
原因就是:%和*有相同的运算优先级(JSL 15.17

一般说来,为了消除魔术数字的负面影响,都命名一些有意义的常量。如是,这个例子的代码可以改成如下形式:
public class Clock2 {

    private static final int MS_PER_HOUR = 60 * 60 * 1000;
    private static final int MS_PER_MINUTE = 60 * 1000;

    public static void main(String[] args) {
        int minutes = 0;
        for (int ms = 0; ms < MS_PER_HOUR; ms++) {
            if (ms % MS_PER_MINUTE == 0) {
                minutes++;
            }
        }
        System.out.println(minutes);
    }
}


如此,魔术数字之错误之虞可消失矣。



  1. JSL 15.17: Multiplicative Operators
Comments