二进制与位运算符的理解与应用

关于二进制


计算机中的任何数据都是二进制形式存储的,需要理解以下几个概念:

  1. 原码: 整数按照绝对值的大小转换成的二进制数,称为原码.负数的原码按照绝对值大小转换成的二进制数,然后最高位补1. 如: 7的原码为: 00000000 00000000 00000000 00000111, -7的原码为: 10000000 00000000 00000000 00000111
  2. 反码: 正数的反码与原码相同, 负数的反码是在原码的基础上除符号位外各位取反. 比如: 10000000 00000000 00000000 00000111的反码为11111111 11111111 11111111 11111000.
  3. 补码: 正数的补码和原码相同, 负数的补码为反码+1;比如: 10000000 00000000 00000000 00000111的补码为11111111 11111111 11111111 11111001. 负数在计算机中是以补码的形式存在的.

可以发现, 正数的原码, 反码, 补码都相同, 这些概念显然是为负数规定的. 所以补码存在的意义是什么呢?
首先要知道, 在计算机中,最大的数+1溢出为0, 根据这个知识, 假设一个正数 n,假设n占一个字节 ,
: 0 = ( 11111111 + 1 ) n n = 11111111 , n + ( n ) = 0 n 已知:0=(11111111+1)\\n | \sim n=11111111,\\n+(-n)=0\\求-n
n = 0 n = ( 11111111 + 1 ) n = ( n n + 1 ) n = n + 1 -n=0-n=(11111111+1)-n=(n|\sim n+1)-n=\sim n+1
所以, 负数可以用对应的正数取反+1表示, 这就是补码.
使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。

位运算


位运算符实际上就是二进制的运算

假设数字占一个字节

  1. 与( & )
    比如: 6 & 7
    先将两个十进制的数换算成二进制:
    5: 0000 0101
    9: 0000 1001
    然后将对应位进行与运算, 可得结果为: 0000 0001
    最后再换算为十进制: 1
    即 5 & 9 = 1
  2. 或( | )
    和与运算类似, 先将两个十进制的数转换为二进制,再进行或运算.
    如: 5 | 9 = 13
  3. 异或( ^ )
    异或: 相同时是false, 不同时是 true.
    如: 5 ^ 9
    转换成二进制后对应位异或得: 0000 1100
    所以 5 ^ 9 = 12
  4. 取反( ~ )
    将二进制数中所有位 ( 包括符号位 ) 0变成1,1变成0.
  5. 左移( << )
    把所有位向左移动规定的位数, 低位补0.
    如: 9 << 2
    9的二进制: 0000 1001
    得到的二进制数为: 0010 0100
    其值为36
    容易知道 x < < n = x 2 n x<<n=x*2^n
  6. 右移( >> )
    与左移类似, 将所有位向右移动规定的位数, 高位负数补1, 正数补0.
    如: 9 >> 2
    得到的二进制数: 0000 0010, 值为2
    -9>>2
    -9的二进制( 补码 ): 1111 0111
    得到的二进制数: 1111 1101
    原码为: 1000 0011, 值为-3
    容易知道: x > > n = x / 2 n x>>n=x/2^n
  7. 无符号右移( >>> )
    与右移的区别在于补位的时候无论正数还是负数,都补0.

位运算符的应用


使用位运算符常常可以使程序更加炫酷简洁

  1. 判断奇偶数
    判断二进制数最后一位是0还是1
    a & 1 == 0时a为偶数
  2. 取余
    a对 2 n 2^n 取余,可以 a a & ( 2 n 1 ) (2^n-1) 结果就是余数.
    原理就是返回 2 n 2^n 位后面的数
    这样取余效率高很多.
  3. 求相反数
    ~a + 1
  4. 求绝对值
    a >> 31 == 0 ? a : (~a + 1)
    原理就是通过二进制的最高位判断正负.

参考:
位运算符与常用的使用场景

发布了7 篇原创文章 · 获赞 2 · 访问量 214

猜你喜欢

转载自blog.csdn.net/qq_44000076/article/details/103957284