一、统计一个数二进制中1的个数
题目内容
写一个函数返回参数二进制中1的个数例如:15 00001111 4个1
第一种解法
#include <stdio.h> int NumberOf1(unsigned int n) { int count = 0; while (n) { if (n % 2 == 1) count++; n /= 2; } return count; } int main() { int n = 15; printf("%d\n", NumberOf1(n)); return 0; }
运行结果为:
第一种解法的思路是:
//15 % 2 = 1 15的二进制00001111//15 / 2 = 7//7 % 2 = 1 7的二进制00000111
//7 / 2 = 3
//3 % 2 = 1 3的二进制00000011
//3 / 2 = 1
//1 % 2 = 1 1的二进制00000001
//1 / 2 = 0
缺陷是这个逻辑只能用于正整数,遇到负数我们只能将函数的参数设定为unsigned int类型才能运行正常
第二种解法
#include <stdio.h> int NumberOf1(int n) { int count = 0,i; for (i = 0; i < 32; i++) { if (((n >> i) & 1) == 1) count++; } return count; } int main() { int n = -1; printf("%d\n", NumberOf1(n)); return 0; }
运行结果为:
第二种解法的思路是:
//15 00000000000000000000000000001111 原码 // 00000000000000000000000000001111 反码 // 00000000000000000000000000001111 补码 //1 00000000000000000000000000000001 //15&1 00000000000000000000000000000001 //15>>1 00000000000000000000000000000111 //1 00000000000000000000000000000001 //(15>>1)&1 00000000000000000000000000000001 //...... //-1 10000000000000000000000000000001 原码 // 11111111111111111111111111111110 反码 // 11111111111111111111111111111111 补码 //1 00000000000000000000000000000001 //-1&1 00000000000000000000000000000001 //-1>>1 11111111111111111111111111111111 // 1 00000000000000000000000000000001 //(-1>>1)&1 00000000000000000000000000000001 // ...... //将-1依次>>32位,计算出所有的1就结束
第三种解法(优解)
#include <stdio.h> int NumberOf1(int n) { int count = 0; do count++; while (n = n & n - 1); return count; } int main() { int n = -1; printf("%d\n", NumberOf1(n)); return 0; }
运行结果为:
第三种解法的思路是:
//15 1111 //15-1 = 14 1110 //15&14 1110 //n = 15%14 //15&14 1110 //(15&14)-1 1101 //两数& 1100 //n = (15&14)&((15&14)-1) //n 1100 //n-1 1011 //n&n-1 1000 //n = n&n-1 //n 1000 //n-1 0111 //n&n-1 0000 //n = n&n-1 //n == 0 //如此反复运行n = n&n-1,直到n = 0时停止 //因而n&n-1能去掉一个数二进制中的一个1
相关问题
判断一个数是否为2的n次方
#include <stdio.h> int main() { int n = 2048; if ((n & n - 1) == 0) printf("该数是2的n次方\n"); else printf("该数不是2的n次方\n"); return 0; }
运行结果为:
二、求两个数二进制中不同位的个数
题目内容
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?输入例子:1999 2299输出例子:7
第一种解法
#include <stdio.h> int main() { int m = 0, n = 0, count = 0, i = 0; scanf("%d %d", &m, &n); for (i = 0; i < 32; i++)//循环32次 { if (((m >> i) & 1) != ((n >> i) & 1))//第一个整数与第二个整数二进制位不同时count++ count++; } printf("%d\n", count); return 0; }
运行结果为:
第一种解法的思路是:
分别给第一个整数和第二个整数&1,将得到的值进行对比,如果不同,则记为不同位的第一个;随后二进制右移一位再进行对比,如不同,则记为不同位的第二个;如此循环32位即可得到最终结果。第二种解法(优解)
#include <stdio.h> int NumberOf1(int n) { int count = 0; do count++; while (n = n & n - 1); return count; } int main() { int m = 0, n = 0, count = 0, ret = 0; scanf("%d %d", &m, &n); ret = m ^ n; //相同的取0,不相同的取1 printf("%d\n", NumberOf1(ret)); return 0; }
运行结果为:
第二种解法的思路是:
将两个数异或一下,异或可以将两个数二进制位中相同的数取0,不相同的取1;而后将异或的结果算出其中有多少个1即可。
三、打印整数二进制的奇数位和偶数位
题目内容
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
解法
#include <stdio.h> int main() { int n,i; scanf("%d", &n); //打印偶数位 for (i = 31; i >= 1; i -= 2) printf("%d ", (n >> i) & 1); printf("\n"); //打印奇数位 for (i = 30; i >= 0; i -= 2) printf("%d ", (n >> i) & 1); return 0; }
运行结果为:
其思路是:
四、交换两个变量(不创建临时变量)
题目内容
不允许创建临时变量,交换两个整数的内容
第一种解法
#include <stdio.h> int main() { int a = 3; int b = 5; printf("a = %d\nb = %d\n\n", a, b); a = a + b; b = a - b; a = a - b; printf("a = %d\nb = %d\n", a, b); return 0; }
运行结果为:
第一种解法是有缺陷的,当要交换的数值过大时,则会溢出
第二种解法(优解)
#include <stdio.h> int main() { int a = 3; int b = 5; printf("a = %d\nb = %d\n\n", a, b); a = a ^ b; b = a ^ b; a = a ^ b; printf("a = %d\nb = %d\n", a, b); return 0; }
运行结果为:
第二种解法的底层逻辑是:
存在一个变量a
一、a ^ a = 0 ,即一个数异或它本身,得到的结果为0。
二、0 ^ a = a ,即一个数异或0,得到的结果为它本身。
五、(单选题)
题目内容
以下系统中,int类型占几个字节,指针占几个字节,操作系统可以使用的最大内存空间是多大:()
A.32位下:4,4,2^32 64位下:8,8,2^64
B.32位下:4,4,不限制 64位下:4,8,不限制
C.32位下:4,4,2^32 64位下:4,8,2^64
D.32位下:4,4,2^32 64位下:4,4,2^64
答案
正确答案应该选: C
六、(单选题)判断代码输出的结果
题目内容
下面代码输出的结果是:()
#include <stdio.h> int main() { int arr[] = { 1,2,3,4,5 }; short* p = (short*)arr; int i = 0; for (i = 0; i < 4; i++) { *(p + i) = 0; } for (i = 0; i < 5; i++) { printf("%d ", arr[i]); } return 0; }
A.1 2 3 4 5B.0 0 3 4 5C.0 0 0 0 5D.1 0 0 0 0
答案
正确答案为: B
解析
十进制:1二进制:00000000 00000000 00000000 00000001十六进制:00 00 00 01
所以最终打印数组arr的情况就为:0 0 3 4 5.