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

本文介绍了四种计算整数二进制表示中1的个数的方法,包括位运算技巧、利用补码特性及标准库函数等。适用于负数补码表示的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

 

方法一、

class Solution {
public:
     int  NumberOf1(int n) {
        int count = 0;
        int flag = 1;
        while (flag != 0) 
        {
            if ((n & flag) != 0) //将1(之后右移)和n进行与运算,判断n的每一位是否是1
            {
                count++;
            }
            flag = flag << 1;//将1每次右移一位
        }
        return count;
     }
};

 

方法二、

有一个数1100,把这个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。1100&1011=1000

class Solution {
public:
     int  NumberOf1(int n) {    
        int count = 0;
        while(n!= 0)
        {
            count++;
            n = n & (n - 1);
        }
        return count;
     }
};

方法三、

首先判断n是不是负数,当n为负数的时候,直接用后面的while循环会导致死循环,因为负数向左移位的话最高位补1 !为了使最高位的符号位1变成0,使用n & 0x7FFFFFFF,把负数转化成正数,最高位由1变成0,因为少了一个1,所以count加1。变成正数后就可以执行while循环。

class Solution {
public:
     int  NumberOf1(int n) {       
        int count = 0;
         if(n < 0){
             n = n & 0x7FFFFFFF;
             ++count;
         }
         while(n != 0){
             count += n & 1;
             n = n >> 1;
         }
         return count;
     }
};

方法四、

标准库提供了bitset类使得处理位集合更容易一些

class Solution {
public:
     int  NumberOf1(int n) {
         bitset<32> bit(n);
         return bit.count(); 
        //合并成一句话:return bitset<32>(n).count();
     }
};

 

按位与运算符(&)

参加运算的两个数据,按二进制位进行“与”运算。

运算规则:0&0=0;  0&1=0;   1&0=0;    1&1=1;

即:两位同时为“1”,结果才为“1”,否则为0

注意:负数按补码形式参加按位与运算。

取反运算符(~)

参加运算的一个数据,按二进制位进行“取反”运算。

运算规则:~1=0;  ~0=1;

即:对一个二进制数按位取反,即0变1,1变0。

“~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。低于 ++,--

左移运算符(<<)

将一个数的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

例:a = a<< 2将a的二进制位左移2位,右补0,

左移1位后a = a *2; 

若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

右移运算符(>>)

将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。

操作数每右移一位,相当于该数除以2。

例如:a = a>> 2 将a的二进制位右移2位,

无符号右移运算符(>>>)

>>>运算符把一个数的各个位向右移指定的位数。右移后左边空出的位用零来填充。移出右边的位被丢弃。

例如:int temp = -14 >>>2

变量 temp的值为 -14 (即二进制的 11111111 11111111 1111111111110010),向右移两位后二进制为 00111111 11111111 1111111111111100)。

不同长度的数据进行位运算

如果两个不同长度的数据进行位运算时,系统会将二者按右端对齐,然后进行位运算。

以“与”运算为例说明如下:我们知道在C语言中long型占4个字节,int型占2个字节,如果一个long型数据与一个int型数据进行“与”运算,右端对齐后,左边不足的位依下面三种情况补足,

(1)如果整型数据为正数,左边补16个0。

(2)如果整型数据为负数,左边补16个1。

(3)如果整形数据为无符号数,左边也补16个0。
 

内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立模块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事模拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值