一、
题目:
求a,b,c的值
nt main() { int a, b, c; a = 5; c = ++a;//c=6,a=6 b = ++c, c++, ++a, a++;//c=8,a=8,b=7 b += a++ + c;//a=9,b=23,注意先使用后++ printf("%a=%d b=%d c=%d:\n", a, b, c); return 0; }
注意:
1、a++,++a,此时a的值自增了1
2、逗号操作符——,,,
三个表达式都需要计算,而最后的值就是最后一个表达式。
3、 +的优先级比+=大
4、b += a++ + c;
b加上的是a原来的值,因为先使用后++
二、
题目:
计算一个参数的二进制位补码的1的个数
TIP:正数的原码补码反码相同,负数存储在内存使用的是补码。
思路一:
这类题型跟计算十进制位中1的个数一样,不同区别就在于一个十进制位,一个二进制位,因此一个/10%10,一个/2%2。
int Numberof1(int n) { int cnt = 0; while (n) { if (n % 2 == 1) { cnt++; } n /= 2; } return cnt; } int main() { int n = 0; scanf("%d", &n); int ret = Numberof1(n); printf("%d\n", ret); return 0; }
这类方法只适用于正数,但也可以在函数用无符号整数进行接收,将-1变成无符号整数,将-1补码的无符号数变为有效位,无符号数的原码补码反码相同,就变成32个1。
思路2:
按位与操作符和移位操作符的结合
按位与&1便于求一个数的二进制位中的最后一个数是1还是0.
注意这个结论可以便于记忆&操作符的作用,一举两得!
一个数&1如果结果是1,说明这个数的二进制位的最低位就是1,&1的结果是0,则就是0。就是原来的数字!
移位操作符,>>向右移动一个二进制位
int Numberof1(int n) { int cnt = 0; for (int i=0;i<=32;i++) { if (n & 1 == 1) { cnt++; } n >>= 1; } return cnt; } int main() { int n = 0; scanf("%d", &n); int ret = Numberof1(n); printf("%d\n", ret); return 0; }
思路三(推荐)
直接n=n&(n-1),并计算执行这一语句的次数,直到n=0.
思路一和思路二算法复杂度都是O(n),而本题的算法复杂度明显要比O(n)少!
int main() { int n = 0; scanf("%d", &n); int cnt = 0; while (n) { n = n & (n - 1); cnt ++ ; } printf("%d\n", cnt); return 0; }
三、
题目:两个整数二进制位中不同位的个数
思路一:
比较笨的算法,上一道题我们已经可以求出二进制中的每一位,所以这一道题可以沿用上一道的算法,将这两个数的二进制位的每一位进行比较。
int solve(int a, int b) { int cnt = 0; for (int i=0;i<32;i++) { if (((a>>i) & 1) != ((b>>i) & 1)) { cnt++; } } return cnt; } int main() { int a, b = 0; scanf("%d %d", &a, &b); int ret = solve(a, b); printf("%d\n", ret); return 0; }
思路2:
介绍另外一个操作符——^ 按位异或
相异为1,相同为0.(注意是针对每一个二进制位,比如整型类型,32位都需要进行按位异或)
可以将两个数直接异或,然后得到的二进制位存储起来,接着再将上面一道题的思路三沿用即可
比思路一更加简便!
int main() { int a, b = 0; scanf("%d %d", &a, &b); int c = a ^ b; int cnt = 0; while (c) { c = c & (c - 1); cnt++; } printf("%d\n", cnt); return 0; }