C语言---求一个整数存储在内存中的二进制中1的个数--3种方法

简介: C语言---求一个整数存储在内存中的二进制中1的个数--3种方法
//编写代码实现:求一个整数存储在内存中的二进制中1的个数
//第一种写法
/*int count_bit_one(unsigned int n)
{
    int count = 0;
    while (n )//除到最后余数是0,那么这个循环就结束了
    {//这个题就是可以想成求15的二进制的过程
        //每次都除以2,余数为1的时候就count++
        if ((n % 2) == 1)//假设输入的是15
            count++;
        n = n / 2;//换下一个数继续除,直到所有的数除完
        //15/2=7  7/2=3  3/2=1  1/2=0,四次计算,每次计算的余数都为1
    }//15的二进制是1111
    return count; 
}
//对于这部分函数不理解的话可以自己画出自己一次计算的一个数的二进制的过程
 
 
int main()
{
    int num = 0;
    scanf("%d", &num);
    int ret = count_bit_one(num);
    printf("%d\n", ret);
 
 
    return 0;
}*/
但是我们输入-1,这个输出结果就有问题了
解决方法:传过去num,我们用unsigned int n来接收传过来的数,
使用 unsigned int 在这个函数中是恰当的,因为它确保了
 函数可以正确处理所有非负整数值,并且避免了有符号整数
 可能带来的问题。
 
 
 
 
//第二种算法--不考虑正负号
//-1在内存中的补码是全1
//11111111111111111111111111111111
//不关心符号的写法
 
 
//n&1==1   就说明n的二进制位的最低位是1
//n&1==0   就说明n的二进制位的最低位是0
 
//计算完这一位,想要计算下一位,那么就需要用到
//右移操作符了
//把n的二进制数的每一位都移到最低位
//00000000000000000000000000000001--1的补码
//因为&的用法是对应的二进制位,
// 有0则为0,两个同时为1才为1
//如果n的二进制数最低位和1的二进制数最低位产生反应,
//那么两个1就会场生一个1,
// 如果n的最低位数字是0,那么产生的数字仅仅是0
/*int count_bit_one(int n)
{
    int count = 0;
    for (int i = 0; i < 32; i++)
    {//有0则为0,两个同时为1才为1
        if ((n >> i) & 1 == 1)//i是从0开始的,也就是最开始的n的最低位
            //然后利用右移操作符依次变更最低位的数字
        {
            count++;//如果结果为1那么就++
        }   
    }
 
    return count;
}
 
 
int main()    
{    
    int num = 0;    
    scanf("%d", &num);  
    int ret = count_bit_one(num);   
    printf("%d\n", ret);    
 
 
    return 0;   
}    */
 
 
 
//第三种写法
//铺垫
/*
n=11   n=n&(n-1)
二进制
一开始:
n  = 1011
n-1= 1010
赋值后:   
n=n&(n-1),   &有 0就是0,两个1就是1
得到一个新的n
n  = 1010
n-1 =1001
再次用新得来的n和n-1来为新的n赋值
n=n&(n-1)
n   =    1000
n-1 =    0111
再次赋值
n=n&(n-1)
n=0000
 
 
n从最开始的1011不断赋值到0000,
n=n&(n-1)这个方程把n的二进制序列中的最右边的1去掉了
*/
 
 
//即通过反复应用 n = n & (n - 1); 直到 n 变为0,
// 每次操作清除一个1,计数器增加1,最后得到1的总数。
 
 
 
int count_bit_one(int n)
{
    int count = 0;
    int i = 0;
 
    while (n)//循环停下来的时候n就变成0了
    {
        n = n & (n - 1);//执行一次就会去掉一个1
        count++;
    }
 
    return count;
}
 
 
 
 
int main()
{
    int num = 0;
    scanf("%d", &num);
    int ret = count_bit_one(num);
    printf("%d\n", ret);
 
 
    return 0;
}    
 
 
 
每次执行 n = n & (n - 1); 都会减少 n 的二进制表示中1的个数,直到没有1剩下,此时 n 变为0,循环结束。
相关文章
|
22天前
|
机器学习/深度学习 算法 物联网
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
本文介绍了两种大模型微调方法——LoRA(低秩适应)和PPO(近端策略优化)。LoRA通过引入低秩矩阵微调部分权重,适合资源受限环境,具有资源节省和训练速度快的优势,适用于监督学习和简单交互场景。PPO基于策略优化,适合需要用户交互反馈的场景,能够适应复杂反馈并动态调整策略,适用于强化学习和复杂用户交互。文章还对比了两者的资源消耗和适用数据规模,帮助读者根据具体需求选择最合适的微调策略。
|
21天前
|
缓存 监控 Java
在使用 Glide 加载 Gif 动画时避免内存泄漏的方法
【10月更文挑战第20天】在使用 Glide 加载 Gif 动画时,避免内存泄漏是非常重要的。通过及时取消加载请求、正确处理生命周期、使用弱引用、清理缓存和避免重复加载等方法,可以有效地避免内存泄漏问题。同时,定期进行监控和检测,确保应用的性能和稳定性。需要在实际开发中不断积累经验,根据具体情况灵活运用这些方法,以保障应用的良好运行。
|
21天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
44 1
|
26天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
30天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
53 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
存储 程序员 C语言
程序员之路:C语言中存储类别
程序员之路:C语言中存储类别
133 0
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
33 3
|
6天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
21 6
|
26天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
34 10