判断一个整数是否是奇数

## 问题:判断一个整数是否是奇数
> 注:来源于知乎一篇文章[记一道简单的java面试题](https://zhuanlan.zhihu.com/p/57859872 "记一道简单的java面试题") 这里记录一下几种写法 

### 常规取模方式
需要注意:java中负数取模操作会有负数的结果。
```java
public boolean isOdd1(int num) {
	return (num % 2) != 0;
}
```

### 移位方式
先右移1位,再左移1位:相当于将一个整数先除2,得到的整数部分再乘2,判断结果是否等于原来的数,不同则为奇数。
```java
public boolean isOdd2(int num) {
	return (num>>1<<1) != num;
}
```
### 与("&")方式
按位与运算:二进制中,1只有最低位为1,其余都为0,任何数和1与运算,除了最低位,其余位一定得0,所以`num & 1`等同于最低位在进行与运算,若与结果为1,表示最低位为1,即是奇数。
```java
public boolean isOdd3(int num) {
	return (num & 1) == 1;
}
```

------------

### 哪种方式更快一点
知乎大佬的说法:按理说位运算操作更快一点,但是实际测试却是时间差不多,原因是"编译器会将对2的指数的取模操作,优化成位运算操作"。

但我这边的测试结果显示~~与运算最快,移位操作最慢~~ (测试方法存在问题,一来ms级时间误差太大,二来执行的时间并不稳定),而从javap和JD-GUI反编译结果来看,似乎java也并没有在编译阶段对取模操作优化

- ~~ms级测试~~

```java
@Test
public void oddtimeTest() {
	Odd o = new Odd();
	long time = System.currentTimeMillis();
	for (int i = 0; i < 10000000; i++) {
		o.isOdd1(i);
	}
	long time1 = System.currentTimeMillis();
	for (int i = 0; i < 10000000; i++) {
		o.isOdd2(i);
	}
	long time2 = System.currentTimeMillis();
	for (int i = 0; i < 10000000; i++) {
		o.isOdd3(i);
	}
	long time3 = System.currentTimeMillis();
	System.out.println(time1 - time + "ms");
	System.out.println(time2 - time1 + "ms");
	System.out.println(time3 - time2 + "ms");
}
```

某次执行结果:
![](https://img.yebukong.com/blog/1101070795486109697/TIM20190228195400.png)

- ns级测试 : 依然有运行误差,但大部分结果为取模运算最慢

```java
@Test
public void oddtimeTest() {
	Odd o = new Odd();
	long time = System.nanoTime();
	for (int i = 0; i < 10000000; i++) {
		o.isOdd1(i);
	}
	long time1 = System.nanoTime();
	for (int i = 0; i < 10000000; i++) {
		o.isOdd2(i);
	}
	long time2 = System.nanoTime();
	for (int i = 0; i < 10000000; i++) {
		o.isOdd3(i);
	}
	long time3 = System.nanoTime();
	System.out.println(time1 - time + " ns");
	System.out.println(time2 - time1 + " ns");
	System.out.println(time3 - time2 + " ns");
}
```

某次执行结果:
![](https://img.yebukong.com/blog/1101070795486109697/TIM截图20190325160841.png)

### javap -c 查看class
```java
PS D:\WorkSpace\MyEclipse\TestCode\target\classes\pers\mine\TestCode> javap -c .\Odd.class
Compiled from "Odd.java"
public class pers.mine.TestCode.Odd {
  public pers.mine.TestCode.Odd();
    Code:
       0: aload_0
       1: invokespecial #8     // Method java/lang/Object."<init>":()V
       4: return

  public boolean isOdd1(int);
    Code:
       0: iload_1               //从局部变量1中装载int类型值
       1: iconst_2              //将int类型常量2压入栈
       2: irem                  //计算int类型除法的余数
       3: ifeq          8       //如果等于0,则跳转到8
       6: iconst_1              //将int类型常量1压入栈
       7: ireturn               // 从方法中返回int类型的数据
       8: iconst_0              //将int类型常量0压入栈
       9: ireturn               //从方法中返回int类型的数据
                                
  public boolean isOdd2(int);
    Code:
       0: iload_1        		//从局部变量1中装载int类型值
       1: iconst_1       		//将int类型常量1压入栈
       2: ishr           		//执行int类型的向右移位操作
       3: iconst_1       		//将int类型常量1压入栈
       4: ishl           		//执行int类型的向左移位操作
       5: iload_1        		//从局部变量1中装载int类型值
       6: if_icmpeq     11      //比较栈顶两int型数值大小,当结果等于0时跳转
       9: iconst_1              //将int类型常量1压入栈
      10: ireturn               //从方法中返回int类型的数据
      11: iconst_0              //将int类型常量0压入栈
      12: ireturn               //从方法中返回int类型的数据

  public boolean isOdd3(int);
    Code:
       0: iload_1               //从局部变量1中装载int类型值
       1: iconst_1              //将int类型常量1压入栈
       2: iand                  //将栈顶两int型数值作“按位与”并将结果压入栈顶
       3: iconst_1              //将int类型常量1压入栈
       4: if_icmpne     9       //比较栈顶两int型数值大小,当结果不等于0时跳转
       7: iconst_1              //将int类型常量1压入栈
       8: ireturn               //从方法中返回int类型的数据
       9: iconst_0              //将int类型常量0压入栈
      10: ireturn               //从方法中返回int类型的数据
}
```

### JD-GUI查看class
![](https://img.yebukong.com/blog/1101070795486109697/TIMgui0190301210606.png)

### 进行测试的java版本
```
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
```
:flushed:


------------
> 本文由 [叶不空](https://yebukong.com "叶不空") 创作,采用 [知识共享署名 4.0 国际许可协议](https://creativecommons.org/licenses/by/4.0/ "知识共享署名 4.0 国际许可协议")进行许可,转载请附上链接!
> 本文链接: [https://yebukong.com/article/1101070795486109697.html](https://yebukong.com/article/1101070795486109697.html "判断一个整数是否是奇数")
                        
(°ο°)评论插件未能完成加载!