前言:因为此题目要用到位运算的知识,所以就简单介绍下位运算
问题:
1、为什么所有的IT编程人员都如此推崇位运算呢?
2、为什么位运算的效率比普通的加减乘除效率高呢?
那么,看完这两个问题后有没有想要了解位运算的冲动呢?下面让我们来了解下位运算。
位运算: 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。
计算机的运算模式是以二进制为基础,所以十进制在计算时会被转换成二进制再进行运算,而转换过程会导致运行速度降低。
看完上面两个名词的解释,位运算效率高的原因就是计算机的CPU在进行计算时是直接使用数字在内存中的存储形式(二进制)进行计算的;而加减乘除等运算会先解释符号含义,然后再通过ALU(算数逻辑单元)进行计算得出结果,这样的话,效率当然没有位运算高了。
看完上面两个名词的解释,位运算效率高的原因就是计算机的CPU在进行计算时是直接使用数字在内存中的存储形式(二进制)进行计算的;而加减乘除等运算会先解释符号含义,然后再通过ALU(算数逻辑单元)进行计算得出结果,这样的话,效率当然没有位运算高了。
位运算的运算符:
and运算 &
|
按位与
|
or运算 |
|
按位或
|
xor运算 ^
|
按位异或 |
not运算 ~
|
按位取反
|
shl运算 <<
|
左移 |
shr运算 >>
|
右移
|
示例一:
我们可以用下面的代码来计算一个32位整数的
二进制中1的个数的奇偶性,当输入数据的二进制表示里有偶数个数字1时程序输出0,有奇数个则输出1。例如,1314520的二进制101000000111011011000中有9个1,则x=1314520时程序输出1。
//c/c++代码
int even_ones (unsigned int x) {
x = x^(x >> 1); //(x的最末尾的1位数)——表示原数前两位中1的个数的奇偶性
x = x^(x >> 2); //(x的最末尾的1位数)——表示 原数前四位中1的个数的奇偶性
x = x^(x >> 4); //(x的最末尾的1位数)——表示 原数前八位中1的个数的奇偶性
x = x^(x >> 8); //(x的最末尾的1位数)——表示 原数前十六位中1的个数的奇偶性
x = x^(x >> 16); //(x的最末尾的1位数)——表示 原数前三十二位中1的个数的奇偶性
return x & 1; //取出x的最后一位所表示的数字,并返回
}
解释:
1314520的二进制为101000000111011011000,第一次执行x=x^(x>>1)的结果如下:
0000 0000 0001 0100 0000 1110 1101 1000
0000 0000 0000 1010 0000 0111 0110 1100(XOR)
---------------------------------------------------------------------
0000 0000 0001 1110 0000 1001 1011 0100
得到的结果是一个新的二进制数,其中右起第i位上的数表示原数中第i和i+1位上有奇数个1还是偶数个1。比如,最右边那个0表示原数末两位有偶数个1,右起第3位上的1就表示原数的这个位置和前一个位置中有奇数个1。
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解题思路:将一个整数和整数减1做与运算,这样就可以将该整数最右边的1置零,前面部分不变——根据此条结论,那么一个整数可以做多少次此操作,就说明该整数的二进制中有多少个1。
代码:(C语言实现)
#include <stdio.h> int NumberOf1(int n); int NumberOf1(int n) { int count = 0; while(n) { n = n & (n - 1); count++; } return count; } int main() { int num; int n; printf("请输入一个整数num:"); scanf("%d", &num); n = NumberOf1(num); printf("整数【%d】的二进制中有【%d】个1", num, n); return 0; }
结果: