文章目录
1.写一个函数返回参数二进制中1的个数
1.1解法1
如果我们想得到一个十进制位数它的每一位,我们可以不停的%10,/10;
//1234
1234%10=4
1234/10=123
123%10=3
123/10=12
12%10=2
12/10=1
1%10=1
1/10=0
//一直到/10=0停止
同样的,如果我们想得到一个二进制位数它的每一位;
//11(十进制)->1011(二进制)
11%2=1
11/2=5->101(二进制)
5%2=1
5/2=2
2%2=0
2/2=1
1%2=1
1/2=0
代码如下
int count_num_of_1(int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int n=count_num_of_1(num);
printf("%d\n", n);
}
但是这样写对负数不适用,比如当输入-1时,进入函数内部,-1%2=-1!=1,count不变还是等于0,-1/2=0,while(0)退出循环,返回count等于0.
其实只要把其中一步改一下就行了
int count_num_of_1(unsigned int n)
函数输入一个无符号数
//-1
10000000000000000000000000000001(原码)
11111111111111111111111111111110
11111111111111111111111111111111(补码)
把-1转换为无符号数,那么第一位的1就不是符号位,-1转化为无符号数等于2^32-1,一个非常大的正数,然后可以正常进行%2,/2运算,计算1的个数
1.2解法2
一个数&1,结果为1,那么它二进制位的最低位为1;结果为0,那么它二进制位中最低位为0。然后>>将这个数的每一位都&1,这样就可以得到这个数二进制位的每一位。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int count_num_of_1(int n)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
{
count++;
}
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int n = count_num_of_1(num);
printf("%d\n", n);
}
这个解法对负数也适用。
1.3解法3
这种方法不容易想到
n=n&(n-1)
n=15
1111 n
1110 n-1
1110 n
1101 n-1
1100 n
1011 n-1
1000 n
0111 n-1
0000 n
我们可以发现n=n&(n-1)这个表达式每运行一次,二进制位中最右边的1就被去掉了,所以这个表达式运行了几次就代表二进制位中有几个1。
int count_num_of_1(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int n = count_num_of_1(num);
printf("%d\n", n);
}
这个解法对负数也适用。
n&(n-1)这个表达式还有一个用途
判断一个数是不是2^n.
if(n&(n-1)==0)
因为n&(n-1)这个表达式执行一次去掉一个1,而2^n的二进制位中只有一个1,去掉就为0.
2.两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
2.1解法1
我们可以把两个数二进制位中每一位都取出来,挨个进行比较。
int count_diff_bit(int m, int n)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (((m >> i) & 1) != ((n >> i) & 1))
{
count++;
}
}
return count;
}
int main()
{
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int ret=count_diff_bit(m, n);
printf("%d\n", ret);
return 0;
}
2.2解法2
^ 异或操作符
相同为0;不同为1
通过计算1的个数,可以得到有多少个位不同。
int count_diff_bit(int m, int n)
{
int count = 0;
int ret = m ^ n;
while (ret)
{
ret = ret & (ret - 1);
count++;
}
return count;
}
int main()
{
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int ret = count_diff_bit(m, n);
printf("%d\n", ret);
return 0;
}
3.获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列。
可以用到前面获取二进制每一位的算法。
int main()
{
int num = 0;
scanf("%d", &num);
//10
//00000000000000000000000000001010
int i = 0;
for (i = 30; i >= 0; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
for (i = 31; i >= 1; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
return 0;
}
4.下面代码的结果是:
#include <stdio.h>
int i; //0
int main()
{
i--; /-1
if (i > sizeof(i)) //-1>4
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
题目内容:
A .>
B .<
C .不输出
D .程序有问题
全局变量,静态变量都是放在静态区的。
全局变量和静态变量不初始化的时候,默认都会被初始化为0。
局部变量,是放在栈区的,不初始化,默认值是随机值。
sizeof这个操作符计算返回的结果是size_t类型的,是无符号整型。
if (i > sizeof(i)) // -1>4
-1是一个有符号数,它和4这个无符号整数进行比较时,会进行算数转换
类型小于整型的,要进行整型提升。
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类
型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
从下到上进行转换。
-1就转换成无符号数,是一个非常大的数
4,294,967,295
(unsigned int)-1>(unsigned int)4
所以输出结果为:
>
5.输入月份和天数,计算这一年这个月有多少天。
月份 | 天数 |
---|---|
1 | 31 |
2 | 28(平年)/29(闰年) |
3 | 31 |
4 | 30 |
5 | 31 |
6 | 30 |
7 | 31 |
8 | 31 |
9 | 30 |
10 | 31 |
11 | 30 |
12 | 31 |
int is_leap_year(int y)
{
return ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0));//&&,||,算出结果为真->1;结果为假->0.
}//判断是否为闰年,是返回1,不是返回0
int main()
{
int y = 0;
int m = 0;
int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
while (scanf("%d %d", &y, &m) == 2)
{
int d = days[m];//输入的月份对应数组的下标
if (is_leap_year(y) == 1 && m == 2)//是闰年的二月天数+1
{
d++;
}
printf("%d\n", d);
}
return 0;
}