今天在看逛博客的时候看到了这么一道Java面试题:
完成代码,判断奇偶数:
public boolean isOdd(inti)
这道题原来是发表在知乎上的一片文章
原文说大多数面试者看到这道题后给出了如下的代码:
public boolean isOdd(inti){
if (i % 2 == 1) {
System.out.println("是奇数");
} else {
System.out.println("是偶数");
}
}
尝试编译就会发现这段代码会出错
为啥呢?
这是因为面试这没注意到题目中的public boolean 他返回的结果是布尔型。而什么时布尔型呢?
在四则运算的程序开发中,需要解析计算表达式,并判断表达式的正确性。因此程序需要把判断结果存储在一个变量中,用于控制程序执行不同的分支语句,这个变量的类型就是布尔型。
布尔类型是用来表达逻辑判断的类型,在Java中通过boolean来定义布尔类型,它的返回值只有 true和false两个值来代表布尔逻辑中的真和假。
看到这就会改成如下代码:
public boolean isOdd(int i) {
if (i % 2 == 1) {
return true;
} else {
return false;
}
但是很明显在if括号中的判断语句返回的也是boolean类型的值,那么代码就能改成如下代码:
public boolean isOdd(int i) {
return i % 2 == 1;
}
在这儿大部分人都会觉得这道题已经完了,但是这里有个陷阱:
你要判断的数i它是一个int类型,而int类型中有一半是负数。而%在返回一个数时,它的符号会跟%左边操作数的符号一致,所以return i % 2 == 1这段语句在返回所有的负数时返回的值都为-1,经过判断结果都是false,所以当i为负时有一半的负数判断时错误的。所以我们要做出如下改动:
public boolean isOdd(int i) {
return i % 2 != 0;
}
那么问题又来了,有没有取模运算更快的方法呢?
在这里很多人都想不到这个方法。
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算,就是直接对整数在内存中的二进制位进行操作。计算机识别速度更快所以按位运算比普通的运算更加快。
在十进制数转化为二进制的数的时候,奇数的二进制数最后一位都会是1,偶数的最后一位都为0,想想按位运算都有那些
所以这个程序会改成如下:
public boolean isOdd(int i) {
return (i&1)==1;
}
但是为什么我们平时很少见到有人这么写呢?
原因有两点:
一是这么写的话代码不容易理解,可读性差;
二是在编译器上运行时,编译器会将对2的指数的取模操作,优化成位运算操作。所以这两种方法在编译器上执行时速度差不多。