• 【位运算】必知必会:二进制位的原码反码补码转换 以及 按位与&、按位或|、异或^


    二进制位的原码反码补码转换 以及 按位与&、按位或|、异或^

    最近在练习LeetCode上的算法题,遇到了位运算求解的问题,作以复习总结。

    一、二进制位的原码、反码、补码转换

    在计算机当中都是使用补码来进行计算和存储的。
    反码解决了正确计算负数问题;
    补码很好的解决了反码 负数不能跨零计算的弊端;
    并且补码还可以记录一个特殊的值 -128,这个数据在 1 个字节下是没有原码和反码。

    正数的原码反码补码相同;
    负数的原码—>反码: 符号位不变,其余各位取反;
    负数的反码—>补码: 反码加上1(相当于将原码数值位取反然后在最低位加1) ;


    1.机器数

    机器数:一个数在计算机中的表示形式是二进制;
    机器数通常是带有符号的(指有正数和负数之分),计算机用最高位存放符号,这个 bit 一般叫做符号位正数的符号位为 0, 负数的符号位为 1

    比如,十进制中的数 +7 ,计算机字长为8位,
    	 转换成二进制就是 0 0 0 0 0 1 1 1(一个 byte 有 8bit,有效的取值范围是 -128 ~ +127)。
          如果是 -7 ,就是1 0 0 0 0 1 1 1。
    
    • 1
    • 2
    • 3

    计算机底层使用二进制形式的补码来计算和存储数据

    一个存储的二进制码分原码、反码、补码!

    2.原码

    十进制数据的二进制表现形式就是原码,原码最左边的一个数字就是符号位,0为正,1为负。

    左边第一位为符号位,其他位为数据位。

    一个 byte 有 8bit,最大值是 0 1 1 1 1 1 1 1(+127),最小值是 1 1 1 1 1 1 1 1(-127)

    在计算机中之所以使用二进制来表示原码是因为逻辑简单,对于电路来说只有开或者关两种状态,用二进制是在方便不过的了。

    计算:

    使用原码对正数进行计算不会有任何问题的。
    但是如果是负数的话,那计算的结果就会大相径庭了。

    例如 :5+2
    	 0 0 0 0 0 1 0 1
    	+        0 0 1 0
    	-----------------
    	 0 0 0 0 0 1 1 1
    结果没问题,值为7.
    
    如果是负数,-56 -1
    	 1 0 1 1 1 0 0 0
    	-              1
    	 -----------------
    	 1 0 1 1 0 1 1 1
    显然结果不应该是-55!减一之后正确的结果应该是 -57(1 0 1 1 1 0 0 1)才对。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    为了解决原码不能用于计算负数的这种问题,这时候,反码它出现了,作为负数的“计算的救星”。

    计算规则是正数的反码不变和原码一致,负数的反码会在原码的基础上,高位的符号位不变,其他位取反( 1 变成 0 , 0 变为 1 )

    3.反码

    正数的反码是其本身(等于原码),负数的反码是符号位保持不变,其余位取反。反码的存在是为了正确计算负数,因为原码不能用于计算负数。

    十进制数字原码反码
    +00000 00000000 0000
    -01000 00001111 1111
    -11000 00011111 1110

    负数计算
    这时候,我们再来使用反码计算一下 -56 - 1 的结果。

    -56 的原码是1 0 1 1 1 0 0 0,如果转成反码(符号位不变,其他位取反)

    那么它的反码就是1 1 0 0 0 1 1 1

      1 1 0 0 0 1 1 1
     -              1
    -----------------
      1 1 0 0 0 1 1 0
    
    -56 -1 = -57,-57 的原码是1 0 1 1 1 0 0 1,转成反码刚好是1 1 0 0 0 1 1 0,刚好等于刚才我们算出的值。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    跨零计算
    不过反码也有它的 “ 软肋 ”,如果是负数跨零进行计算的话,计算得出的结果不对.

    -3 + 5 来举例

    -3 的原码是1 0 0 0 0 0 1 1,转成反码的话就是 1 1 1 1 1 1 0 0

     1 1 1 1 1 1 0 0
    +        0 1 0 1  
    -----------------
     0 0 0 0 0 0 0 1
    把计算结果转成十进制就是 1,这结果显然不对。那么我们该怎么计算呢,这时候,作为反码的补充编码 —— 补码就出现了。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    作为反码的补充编码 —— 补码就出现了。

    4.补码

    正数的补码是其本身,负数的补码等于其反码 +1。因为反码不能解决负数跨零(类似于 -6 + 7)的问题,所以补码出现了。

    跨零计算
    这时候,我们再来使用反码计算一下 -3 + 5 的结果。

    -3 的原码是1 0 0 0 0 0 1 1,转成反码的话就是 1 1 1 1 1 1 0 0,再转成补码就是1 1 1 1 1 1 0 1

     1 1 1 1 1 1 0 1
    +        0 1 0 1
    ----------------- 
     0 0 0 0 0 0 1 0
    结果正确。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、按位与&、按位或|、异或^

    运算符含义运算规则用途
    &位与两个位都是1,结果为1,其他为01.判断奇偶数:用if ((a & 1) == 0) 代替 if (a % 2 == 0)来判断a是不是偶数;2.取余:让a对16进行取余,那么就可以让 a & 15
    |位或两个位都是0,结果为0,其他为1
    ^位异或同0异1:相同为0,不同为1交换两个数:(a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a,a^0=a
    ~位非0变1,1变0求相反数: ~a + 1
    <<左移向左移动,低位补零做 * (2 ^ n)的运算
    >>右移向右移动,高位补零,符号位按照原来数字的符号位不变1.做 / (2 ^ n)的运算;2.求绝对值: a >> 31 == 0 ? a : (~a + 1)
    >>>无符号右移向右移动,高位补零-

    下一篇有关于位运算实际使用的介绍!

  • 相关阅读:
    车间调度|基于帝王蝶优化算法的车间调度(Matlab代码实现)
    tsne可视化cnn模型
    MySQL基础-多表查询
    GaussDB技术解读系列:HTAP方向的探索与发展
    【c++】对象与对象之间的关系
    C Primer Plus(6) 中文版 第10章 数组和指针 10.4 函数、数组和指针
    apache中的ab压测
    基于OpenHarmony L2设备,如何用IoTDeviceSDKTiny对接华为云
    【Unity】Unity开发进阶(八)Windows解析Excel报错问题、跨平台解析Excel文件
    Android 唤醒屏幕的方式:屏幕锁 - WakeLock / FLAG_KEEP_SCREEN_ON
  • 原文地址:https://blog.csdn.net/weixin_43431218/article/details/133858292