题目很简单,完成代码,判断一个整数是否是奇数:
public boolean isOdd(int i)
这道笔试题好多答案都长这样(换做是我,我第一反应应该也是这样了...):
public boolean isOdd(int i) {
if (i % 2 == 1) {
System.out.println("是奇数");
} else {
System.out.println("是偶数");
}
}
然后编译一下,发现错误了再改成这样(报错是因为缺少返回类型):
public boolean isOdd(int i) {
if (i % 2 == 1) {
return true;
} else {
return false;
}
}
进行引导:
“这个函数的定义要求返回一个什么类型的值?”
“布尔类型。”
“那么,你if后面的括号里面的表达式的值是一个什么类型的?”
“也是布尔类型。”
遂能够把代码优化成这样:
public boolean isOdd(int i) {
return i % 2 == 1;
}
继续进行引导:
“那我传进来一个-1呢?”
“从小被教导只有自然数才有奇数偶数之分,负数没有奇偶这一说。”
“是吗?”
有的人能接受这个设定,就会把代码改成这样:
public boolean isOdd(int i) {
return i % 2 == 1 || i % 2 == -1;
}
//并且在提示之后优化成这样:
public boolean isOdd(int i) {
return i % 2 != 0;
}
继续引导:
“有更好的办法吗?”
“?”
“我觉得取模操作比较慢,有更快的解决方案吗?”
除了少数人能自己想想就想出来了之外,绝大部分表示没有或者不知道,于是进行下一步提示:
“奇数和偶数转换成二进制有什么区别?”
“奇数最后一位是1,偶数最后一位是0。”
“然后呢?”
这里很奇怪,大部分能聊到这里来的候选人会想起来移位操作,但不知道是为什么,虽然这道题确实可以有这种操作(但这个根根本不是重点好吧!):
public boolean isOdd(int i) {
return i >> 1 << 1 != i;
}
应该是写成下面这样的:
public boolean isOdd(int i) {
return (i & 1) == 1;
}
“这样是不是比上面取模运算要快?”
“那当然了,位运算肯定快啊。”
“但是我们实际代码测试过,发现上面的按位与操作和取模操作,实际运行的时间是差不多的,为什么呢?”
“编译器会将对2的指数的取模操作,优化成位运算操作。”
补充按位与的操作原理: