C/C++程序设计11:【面试题】32位平台上计算实数对应二进制序列中0和1的个数【模2除2法、位与位或法、移位法】

目录

1 局部变量对全局变量的隐藏问题

2 x & (x-1)的使用分析

3 拓展分析

3.1 利用按位与运算判断一个数是否为2的幂次

3.2 利用按位或判断二进制数中0的个数

3.3 简单循环方法计算0和1的个数

3.4 与1进行按位与的方法


 

今天阅读《程序员面试宝典》时,发现x & (x-1)是一个十分重要且有意思的知识点,在此与各位分享一下

主要内容包含两个知识要点:

(1)局部变量覆盖全局变量时,要使用全局变量需加【::】修饰符

(2)x & (x-1)隐藏的秘密

直接上代码:

#include <iostream>
using namespace std;
int i = 0;
int func(int x)
{
	while(x)
	{
		x = x & (x-1);
		i++;
	}
	return i;
}
int main()
{
	int i = ::i;
	cout << func(9999) << endl;
	cout << i << endl;
	return 0;
}

1 局部变量对全局变量的隐藏问题

在main函数代码中,我们使用全局变量 i 为同名的局部变量 i 赋值,使用到了【::】运算符;如果没有改运算符,会报以下错误:

这也是一个比较经典的面试题,值得关注一下。

2 x & (x-1)的使用分析

func函数的作用实际上是获得定参数x转为二进制时包含的1的个数,代码执行过程如下:

3 拓展分析

3.1 利用按位与运算判断一个数是否为2的幂次

由此可以引伸出,若要判断某个数字是否为2的幂,可采用以下函数实现:

bool isTwoPower(int x)
{
	if((x & (x - 1)) == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

3.2 利用按位或判断二进制数中0的个数

int getZeroCnt(int x)
{
	int cnt = 0;
	while(x + 1)
	{
		x = x | (x + 1);
		cnt++;
	}
	return cnt;
}

3.3 简单循环方法计算0和1的个数

//得到一个数转化为二进制序列后包含的0的个数
int getZeroCnt1(int num)
{
	int count = 0;
	while(num)
	{
		if(num % 2 == 0)
		{
			count++;
		}
		num /= 2;
	}
	return count;
}
//得到一个数转化为二进制序列后包含的1的个数
int getOneCnt1(int num)
{
	int count = 0;
	while(num)
	{
		if(num % 2 == 1)
		{
			count++;
		}
		num /= 2;
	}
	return count;
}
//得到一个二进制数字包含的二进制位数
int getBits(int num)
{
	int count = 0;
	while(num)
	{
		count++;
		num /= 2;
	}
	return count;
}

3.4 与1进行按位与的方法

将这个数与1进行按位与,如果结果是1,那么这个数的最末位就是1,判断完最末位,再将这个数进行右移运算,判断倒数第二位,如此循环32次,就判断出了这个数二进制序列中有多少个数字1。这个方法弥补了模2除2法只能判断正数的缺陷。

int getOneCnt2(int n)
{
    int count = 0;
    int i = 0;
    for (i = 0; i < 32; i++)
    {
        if (((n >> i) & 1) == 1)//一个数与1按位与结果如果是1则这个数的最末位就是1
        {
            count++;
        }
    }
    return count;
}

int getZeroCnt2(int n)
{
    int count = 0;
    int i = 0;
    for (i = 0; i < 32; i++)
    {
        if (((n >> i) & 1) == 0)
        {
            count++;
        }
    }
    return count;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小薛引路

喜欢的读者,可以打赏鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值