(二进制)操作符详解

简介: (二进制)操作符详解

二进制与进制转换

2进制转10进制

无论对应什么进制而言,数值都是每一位的值乘以对应权重之和



10进制转2进制

方法1:不断模2除2取模和整除),直到为0,最后在把余数由下往上组合即为二进制


方法2:当你对2进制熟悉后,可以根据二进制的值进行大致的估算


比如,上图中,求21的二进制,则先估算1111对应15,所以加一位,从10000开始 ,然后看下一位权重为8,加上就超过21了,就再看下一位为4……依此类推,最终算出10101

2进制转8进制和16进制

8进制

从2进制序列中右边低位开始向左每3个2进制位会换算⼀个8进制位,剩余不够3个2进制位的直接换算


16进制

从2进制序列中右边低位开始向左每4个2进制位会换算⼀个16进制位,剩余不够4个2 进制位的直接换算


原码,反码,补码

整数的2进制表示方法有三种,即 原码、反码和补码

有符号 整数的三种表示方法均有符号位和数值位两部分,2进制序列中, 最高位 的1位是被当做 符号位 ,剩余的都是数值位。

符号位都是用 0表示“正” ,用 1表示“负” 。


 


这里有两种方法把补码变回原码第一种是减1,除符号位按位取反,第二种是直接除符号位按位取反,再加1

对于整形来说:数据存放内存中其实存放的是补码。

因为补码与原码相互转换,都可以除符号位按位取反,加1获得,所以运算过程相同


位移操作符


左移操作符

左移抛弃(包括符号位),右边补零;左移不改变m本身,只是会输出一个结果到n

上述例子中,-3的补码是11111111  11111111 11111111 11111101 ,那么我左移30位,最高位就为0,就变成超级大的正数


右移操作符

右移运算分两种(大部分编译器上是算术右移)

1. 逻辑右移:左边⽤0填充,右边丢弃

2. 算术右移:左边⽤原该值的符号位填充,右边丢弃


对于未溢出整数来说,左移一位,相当于乘以2,右移一位,相当于除以2


位操作符

&按位与,有0则为0,全1才为1

| 按位或,有1则为1,全0才为0

^按位异或,相同为0,相异为1


你可以动手算算下面三个位运算哦~


我们再来看看^按位异或的神奇性质,下列输出的a结果为多少?


相信你已经发现了奥秘,在异或的过程中其余数都有伴,而只有6是单身狗,嘻嘻~

所以,两个相同的数异或会消失,只有单独的会留下


我们再来看一道面试题:不能创建临时变量(第三个变量),实现两个数的交换


可能有很多小伙伴是这样实现的,乍一看好像没什么问题,实际上如果a和b是两个非常大的整数,它们之间的运算可能会造成溢出,导致结果出错


实际上,这里利用刚刚异或的性质就能轻松解决 ,这里a先存下a^b,等到与b异或时,里面的b相同就消失了,只剩下a,就可以赋给b;同样,实际上为a的b与实际上为a^b的a异或,a相同就消失了,留下b赋给a

这就好像一个破译密码的过程,a^b是加密过的密文,用a密码本就可以破译出b的信息,用b密码本就可以破译出a的信息


练习

练习1:求一个整数存储在内存中的二进制中1的个数

方法一

根据定义,模2除2,看看有多少1


这样看,好像可以,其实这段代码还有漏洞

当输入的数为负数时,就失效了 。那要怎么改呢?其实很简单,把输入类型改为无符号整型即可,这样编译器就会把负数看为一个特别大的正数了。


方法二

运用位移操作符与位操作符,让每一位与1按位与,1&1为1,0&1为0,这样就可以算出二进制位中有多少个1

方法三

这个方法也是最高效的,利用每运算一次n&(n-1),就会消去二进制中最右边的1的性质


我们可以发现,下图中n每进行一次这种运算,二进制位最右边的1就变成0,直到全为0

这种方式是不是很好?达到了优化的效果,但是难以想到。

这个方法还可以有很多迁移运用,比如这道题:判断一个数n是否是2的次方数


练习2: 二进制位置0或者置1


编写代码将13⼆进制序列的第5位修改为1,然后再改回0


置为1

置为1:将1左移4位,再与13按位或,1和0为1,0和0为0,只把第5位改成1


置为0

置为0:将1左移4位,再按位取反,得到11111111 11111111 11111111 11101111,再去和13按位与,1和0为0,1和1为1,只把第5位改成0


 

练习3:求两个数二进制中不同位的个数


这题其实就是前面练习1的变式,分为两步。第一步,先把两个数异或,根据异或的特点,相同为0,相异为1,这样只要统计1的个数,就是二进制位中不同位的个数。第二步,利用n&(n-1)高效消除1的特点,来统计1的个数


代码如下:


int main()
{
    int a, b;
    while (scanf("%d %d", &a, &b) != EOF)
    {
        int c = a ^ b;
        int count = 0;
        while (c)
        {
            c = c & (c-1);
            count++;
        }
        printf("%d\n",count);
    }
    return 0;
}
相关文章
|
存储 Windows
怎样格式化硬盘?四种硬盘格式化方法(含详细图文步骤)
这篇内容介绍了硬盘格式化的方法,包括为何要格式化硬盘(如快速清空数据、建立新分区、修复错误、改变文件系统类型)和四种格式化方式:1) 使用文件管理器,2) 通过磁盘管理器,3) 利用分区工具DiskGenius,4) 使用diskpart命令。在执行格式化前,务必备份重要数据,因为格式化会导致数据丢失。
|
人工智能 算法
通义千问春节上新,除夕夜AI和你一起过大年!
通义千问春节上新,除夕夜AI和你一起过大年!
757 4
|
2月前
|
存储 缓存 人工智能
大模型应用:大模型数据缓存复用方案:从API请求数据累积到智能融合.50
本文提出一种低成本、高性能的大模型应用优化方案:基于SentenceTransformer本地生成文本向量,实现语义级缓存匹配;结合通义千问大模型智能融合历史与新答案;内置缓存淘汰与异常处理机制。实测缓存命中率超50%,响应提速10倍以上,显著降本增效。
272 4
|
1月前
|
人工智能 Ubuntu Linux
零基础搭建OpenClaw(Clawdbot)智能体|阿里云+本地部署流程+大模型对接+常见问题解答
本文完整覆盖**2026年阿里云轻量服务器部署及本地MacOS/Linux/Windows11部署OpenClaw(Clawdbot)步骤流程及阿里云千问大模型API配置或市场上免费大模型Coding Plan API配置及常见问题解答**,从部署前准备到进阶优化,从核心配置到问题排查,全程提供实战化指引。掌握本文内容,即可避开90%的新手坑,快速让OpenClaw成为办公、学习、生活中的高效助手,真正发挥AI自动化的核心价值。
297 0
|
机器学习/深度学习 前端开发 测试技术
探索软件测试中的自动化测试框架选择与优化策略####
本文深入探讨了在当前软件开发生命周期中,自动化测试框架的选择对于提升测试效率、保障产品质量的重要性。通过分析市场上主流的自动化测试工具,如Selenium、Appium、Jest等,结合具体项目需求,提出了一套系统化的选型与优化策略。文章首先概述了自动化测试的基本原理及其在现代软件开发中的角色变迁,随后详细对比了各主流框架的功能特点、适用场景及优缺点,最后基于实际案例,阐述了如何根据项目特性量身定制自动化测试解决方案,并给出了持续集成/持续部署(CI/CD)环境下的最佳实践建议。 --- ####
|
10月前
|
数据安全/隐私保护
小红书自动评论软件,小红书评论回复脚本,autojs框架分享
该脚本主要实现以下功能模块: 关键词触发机制
|
Linux C语言 编译器
gcc指定头文件路径及动态链接库路径
gcc指定头文件路径及动态链接库路径   本文详细介绍了linux 下gcc头文件指定方法,以及搜索路径顺序的问题。另外,还总结了,gcc动态链接的方法以及路径指定,同样也讨论了搜索路径的顺序问题。
2409 0
|
算法 数据可视化 数据挖掘
R语言确定聚类的最佳簇数:3种聚类优化方法
R语言确定聚类的最佳簇数:3种聚类优化方法
|
存储 安全 算法
信息安全:认证技术原理与应用.
信息安全:认证技术原理与应用.
1076 7