剑指offer——二进制中1的个数

前言:因为此题目要用到位运算的知识,所以就简单介绍下位运算

问题
    1、为什么所有的IT编程人员都如此推崇位运算呢?
    2、为什么位运算的效率比普通的加减乘除效率高呢?

那么,看完这两个问题后有没有想要了解位运算的冲动呢?下面让我们来了解下位运算。
位运算: 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作
计算机的运算模式是以二进制为基础,所以十进制在计算时会被转换成二进制再进行运算,而转换过程会导致运行速度降低。

看完上面两个名词的解释,位运算效率高的原因就是计算机的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;
 }

结果:


猜你喜欢

转载自blog.csdn.net/kangxidagege/article/details/79548564