6.1.通过位运算得到内置类型的最小最大值
1 //获取int型的最大值
2 //get_int_max_1()可能会报错整型常量溢出
3 int get_int_max_1() {
4 return (1 << 31)-1;
5 }
6 int get_int_max_2() {
7 return ~(1 << 31);
8 }
9 //unsigned int 是三十二位的数,右移一位除去符号位
10 int get_int_max_3() {
11 return ((unsigned int)-1) >> 1;
12 }
13 //获取int型最小值
14 int get_int_min_1() {
15 return 1 << 31;
16 }
6.2.左移一位和右移一位的作用
1 //这样思考:1111左移一位11110,相当于每一位在原来的基础上+1,也就是说每一位都翻倍了,转换为十进制的时候也就是说两个1111的十进制结果再相加了
2 //左移一位相当于乘以2
3 int multiply_by_two(int num) {
4 return num << 1;
5 }
6 //右移一位相当于除以2
7 int divide_by_two(int num) {
8 return num >> 1;
9 }
6.3.如何乘以2的n次方或者除以2的n次方
1 //m乘以2的n次方
2 int multiply_by_two_power(int m, int n) {
3 return m << n;
4 }
5 //除以2的m次方
6 int divide_by_two_power(int m, int n) {
7 return m << n;
8 }
6.4判断一个数是否是2的幂
1 //判断一个数是不是2的幂
2 bool isFactorialofTwo(int n) {
3 return n > 0 ? (n & (n - 1)) == 0 : false;
4 }
5 /*如果是2的幂,n一定是100... n-1就是1111....
6 所以做与运算结果为0*/
6.5.从原码到补码你应该领悟到,按位取反+1得到了原码的相反数!
1 //求一个数的相反数
2 int opposite_number(int n) {
3 return ~n + 1;
4 }
6.6.统计一个二进制数中0和1的个数 1 //统计一个二进制数中1和0的个数,n&(~n+1)可以得到最后一位为1的二进制数,n|=(n+1)可以使最后一位0置为1
1 int sum_0(int n) {
2 int count = 0;
3 while (n+1) //全部为1高位去除,结果为0
4 {
5 n |= (n + 1);
6 count++;
7 }
8 return count++;
9 }
6.7.判断一个数的奇偶性
1 //判断一个数的奇偶性
2 //高位去除,得到二进制的最后一位,0为偶数,1为奇
3 bool is_oddnumber(int n) {
4 return (n & 1) == 1;
5 }
6.8.不使用第三个数交换两个数
1 /交换两个数不使用第三个数,把一般运算符的方法也用上了
2 //一个数异或本身等于0,一个数异或0得到本身
3 void swap(int &a,int &b) {
4 a = a ^ b;
5 b = a ^ b;
6 a = a ^ b;
7 }
8 void swap_1(int &a, int &b) {
9 a = a - b;
10 b = a + b;
11 a = b - a;
12 }
6.9.不使用+,-,*,/完成整数相加
1 int Add(int num1, int num2)
2 {
3 int sum, carry;
4 do {
5 //将两个数异或,得到不进位的结果
6 sum = num1 ^ num2;
7 //将两个位运算,得到进位的结果
8 carry = (num1 & num2) << 1;
9 //很显然,我们只要把进位的结果+上不进位的结果就可以得到我们想要的,
10 //但是,我们不能使用+运算符,我们知道,进位的结果是1不断的左移,当进位的结果和不进位的结果不断异或,最左边的1
11 //超过了不进位的结果最左边的1,那么最后一次与运算显然结果为0,于是,最后一次异或运算就是我们想要的相加的结果
12 num1 = sum;
13 num2 = carry;
14 } while (num2 != 0); //将结果相加的过程就重复上述过程,直到进位为0
15
16 return sum;
17 }