1.不能创建临时变量,实现两个整数的交换
方法一:加减减,竟可互换
#include <stdio.h> int main() { int a = 5; int b = 3; printf("交换前:a=%d,b=%d\n",a,b); a = a + b; b = a - b; a = a - b; printf("交换后:a=%d,b=%d\n",a,b); //当a,b足够小,但是a+b太大时,可能会溢出 return 0; }
注意:虽然这个方法可以符合要求的交换两个整数,但是有问题的,如果a与b非常大,但是没超出整型大小,然而a+b却有可能溢出,因此这个方法只能解决一部分的情况。
方法二:巧用按位异或
#include <stdio.h> int main() { int a = 5; int b = 3; printf("交换前:a=%d,b=%d\n", a, b); //a^a=0 //0^a=a a = a ^ b; b = a ^ b;//b=a^b^b=a a = a ^ b;//a=a^b^a=b printf("交换后:a=%d,b=%d\n", a, b); //二进制相同位0,相异为1,并不会存在进位问题,所以不会有溢出 return 0; }
使用这个方法我们需要对按位异或运算有所认识,并且了解一些它的运算规律。如有不清楚者,请移步我的主页浏览文章《C语言中移位操作符,位操作符运算规则详解》,里面有非常详细的介绍。
1. a^a=0
2. 0^a=a
2.求一个整数储存在内存的二进制中1的个数
方法一:“%”---“/” 两板斧
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); int count = 0; while (n) { if (n % 2 == 1) { count++; } n /= 2; } printf("%d\n", count); return 0; }
画图演示为:
这与10进制类似,可以按照10进制里%10,/10的思想去思考。
注意: 上述代码中,当n为负整数时是有问题的。我们需要把n定义为unsigned int 类型,这样在我们输入负整数时,n会把它当成无符号整型处理。
方法二:巧用左移操作符和按位与
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); int count = 0; int i = 0; for (i = 0; i < 32; i++) { if ((n >> i) & 1 == 1) count++; } printf("%d\n", count); return 0; }
思路解析如下图:
方法三:n&(n-1)算法
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); int count = 0; while (n) { n = n & (n - 1); count++; } printf("%d\n", count); return 0; }
思路解析如下图:
根据这个算法,我们也可以衍生一个思考题,如何判断一个数是否是2的次方数?
我们可以利用2的次方数的二进制进行判断,2的次方数(设为n)的二进制中,必定有一位是1,其余全是0,所以n&(n-1)若是等于0,则是,否则不是。
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); if (n & (n - 1) ) printf("%d不是2的次方数\n",n); else printf("%d是2的次方数\n", n); return 0; }