关于位运算的一些基础操作

本文解析位运算在解决LeetCode问题中的重要性,讲解了位运算的本质、常见操作及其在ASCII编码中的巧妙运用,揭示了为何频繁使用位运算优化算法效率。通过实例演示,深入剖析位运算在奇偶性判断、位移和位操作中的高效技巧。
摘要由CSDN通过智能技术生成

链接:https://leetcode-cn.com/problems/power-of-two/solution/5chong-jie-fa-ni-ying-gai-bei-xia-de-wei-6x9m/

在解题之前理解一下为什么需要位运算?它的本质是什么?

力扣上不少位运算相关的题,并且很多题也会用到位运算的技巧。这又是为什么?

位运算的由来
在计算机里面,任何数据最终都是用数字来表示的(不管是我们平时用的软件,看的图片,视频,还是文字)。
并且计算机运算单元只认识高低电位,转化成我们认识的逻辑,也就是 0 1 。

这就是导致计算机里面任何数据最终都是用二进制(0 1)来保存的数字。只是我们平时看到的图片、文字、软件都只从二进行数字转化而来的。

位运算符

常用位操作:

1、判断奇偶
(x & 1) == 1 ---等价---> (x % 2 == 1)
(x & 1) == 0 ---等价---> (x % 2 == 0)
x / 2 ---等价---> x >> 1
x &= (x - 1) ------> 把x最低位的二进制1给去掉
x & -x -----> 得到最低位的1
x & ~x -----> 0

2、指定位置的位运算
将X最右边的n位清零:x & (~0 << n)
获取x的第n位值:(x >> n) & 1
获取x的第n位的幂值:x & (1 << n)
仅将第n位置为1:x | (1 << n)
仅将第n位置为0:x & (~(1 << n))
将x最高位至第n位(含)清零:x & ((1 << n) - 1)
将第n位至第0位(含)清零:x & (~((1 << (n + 1)) - 1))

3、异或结合律

x ^ 0 = x, x ^ x = 0
x ^ (~0) = ~x, x ^ (~x) = ~0
a ^ b = c, a ^ c = b, b ^ c = a

(有没有点乘法结合律的意思)
字母表示:(a ^ b) ^ c = a ^ (b ^ c)
图形表示:(☆ ^ ◇) ^ △ = ☆ ^ (◇ ^ △)
大小字母位运算技巧

大写变小写、小写变大写:字符 ^= 32 (大写 ^= 32 相当于 +32,小写 ^= 32 相当于 -32)
大写变小写、小写变小写:字符 |= 32 (大写 |= 32 就相当于+32,小写 |= 32 不变)
大写变大写、小写变大写:字符 &= -33 (大写 ^= -33 不变,小写 ^= -33 相当于 -32)

 

把字母当成 8 个bit 位来看,我把大小字母对应的后 4 位圈出来了。

大家有没有发现 A-a B-b ... Z-z 26个字母之间的大小写的后 4 位是完全一样的!!!
(重要知识点1:对应大小字母的 后4位二进制是一样的,后4位二进制是一样的,后4位二进制是一样的)

再来看一下头 4位。对应大小字母之间就第 3位 的 bit 值不一样!!!
(重要知识点2:对应大小字母的前4位中,只有第3位bit值不一样,只有第3位bit值不一样,只有第3位bit值不一样)
把不一样的bit位单独取出来,其它位补 0,也就是 0b0010 0000,对应的十进制数就是 32 !!!

小结1
通过观察,我们发现对应的大小写字母之间,只有第3个bit位的值不一样,已此来做的区分。
那么上面提到的技巧的应用:

字母 ^= 32 其是:字母 ^= 0b10 0000
字母 |= 32 其是:字母 |= 0b10 0000
字母 &= -33 其是:字母 ^= 0b1101 1111
都是针对第3位bit值做的操作,从而可以不用提前知道原字母大小,通过位操作来达到大小写切换。
只有26字母,为什么大小之间的ASCII差值是32,而不是26?
(其实有了上面的了解,再来看这件事就更容易理解了。)

因为字母大小之间的切换是一个很高频的行为,在设计ASCII表时,出于效率的考量,把大小之间的转换需要的 算力 压缩到最小。(关健词:算力)
也就是只需要对一个bit位操作就可以实现大小写之间的切换。

如何压缩算力
如:


int n = 0b100;
n ^= 0b011;
n 最终等于 0b111。虽然只进行了一次 异或 操作,但是对于最底层的 异或 逻辑,是需要对各个bit分别进行一次 异或运算 最终把 3次 的异或累加返回。

同样的逻辑,对应到字母大小之间的切换,每次只需要 1次位操作 就可以得做到大小写切换。(关键词:1次)
从而把大小之间转换的代价压缩到最小。

看到这里,你是不是跟我一样感叹当初设计ASCII表人的牛逼之处了。
是的,ASCII里面的字母序是经过细心设计出来的。

最后
其实明白了这点,返过来看ASCII表的历史就比较有意思了。
我们现在用的ASCII经过3个版本:

1963年由美国标准协会(ANS)制定发布的第一个版
1967年更新第二个版本
1986年更新第三个版本,也就是我们现在任然在使用中的版本
(注:ASCII Wiki)

1986年的时候集成电路的发展还遵循着摩尔定律,并且当时的CPU的计算能力,也没现在这么强劲。
而那个时候 CPU计算力 和 内存 都显得格外的珍贵,像字母大小切换这种高频的操作,能只用 1次 算力解决,绝对不会用2次,甚至更多次。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值