谜题 1:奇数性

以下代码未判断一个数是否为奇数,什么地方有问题?

public static boolean isOdd(int i) {
    return i % 2 == 1;
}

分析

%左边的操作数称为被除数,右边的操作数称为除数

整数求余中,(a/b)*b+(a%b) == a,当b为0,抛出ArithmeticException

对于a = Integer.MIN_VALUE,b = -1也成立(运算过程中发生了溢出)

a/b = Integer.MIN_VALUE(Integer.MAX_VALUE + 1,正整数溢出),a%b = 0

(a/b)*b+(a%b) = Integer.MIN_VALUE * -1 + 0 = Integer.MIN_VALUE == a (Integer.MAX_VALUE + 1,正整数溢出)

(a/b)*b+(a%b) == a 恒等式仍成立

求余是除法运算的隐式运算,余数的符号位同被除数的符号位,因此除数*商的幅度(绝对值)不会超过被除数

public static void testIntegerRemainder() {
    System.out.println("测试【整数求余】运算一般结果");
    int a = 5%3;  // 2
    int b = 5/3;  // 1
    System.out.println("5%3 produces " + a +
            " (note that 5/3 produces " + b + ")");

    int c = 5%(-3);  // 2
    int d = 5/(-3);  // -1
    System.out.println("5%(-3) produces " + c +
            " (note that 5/(-3) produces " + d + ")");

    int e = (-5)%3;  // -2
    int f = (-5)/3;  // -1
    System.out.println("(-5)%3 produces " + e +
            " (note that (-5)/3 produces " + f + ")");

    int g = (-5)%(-3);  // -2
    int h = (-5)/(-3);  // 1
    System.out.println("(-5)%(-3) produces " + g +
            " (note that (-5)/(-3) produces " + h + ")");
}

public static void testDoubleRemainder() {
    System.out.println("测试【浮点数求余】运算一般结果");
    double a = 5.0%3.0;  // 2.0
    System.out.println("5.0%3.0 produces " + a);

    double b = 5.0%(-3.0);  // 2.0
    System.out.println("5.0%(-3.0) produces " + b);

    double c = (-5.0)%3.0;  // -2.0
    System.out.println("(-5.0)%3.0 produces " + c);

    double d = (-5.0)%(-3.0);  // -2.0
    System.out.println("(-5.0)%(-3.0) produces " + d);
}

除整数求余外,Java还可以对浮点数进行求余运算
浮点数运算,满足IEEE754标准,需要注意NaN,即时除数为0,也不会抛出运行时异常,发生溢出,截断,以及损失精度。

在示例中,负奇数余2为-1,因此整数的\(\frac{1}{4}\)的情形都会出错

改正

public static boolean isOdd(int i) {
    return i % 2 != 0;
}

或者

public static boolean isOdd(int i) {
    return (i & 1) != 0;
}

或者

public static boolean isOdd(int i) {
    return (i & 1) == 1;
}

小结

  1. 区分数学上概念和编程实践中的区别
  2. 求余/除法运算结果的的符号位

引用

  1. Java Puzzlers : Traps, Pitfalls, and Corner Cases
  2. The Java® Language Specification Java SE 8 Edition
posted @ 2021-03-12 23:09  蒋智  阅读(85)  评论(0)    收藏  举报