Lua的bit库解读和实践

lua bit

Posted by xiaohao on February 8, 2020

一.位的意思

  • 计算机中的位
    • 二进制数(binary number)用两个数做基础,其中每一个二进制数字(称为位,bit)不是0就是1.
    • 位自右向左,从0开始顺序增量编号,一个8位的二进制数表示为:
下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 0 0 0

假如具体的数字为2的话,就为

下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 0 1 0

计算的结果是:2^1=2

具体的数字为3的话,就为

下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 0 1 1

计算的结果为: 2^0 + 2^1 = 3

  • int8int16int32int64就分别表示为8位的整数,16位的整数,32位的整数,64位的整数.

二.理解位的运算

假如X为2,Y为4,对应位的显示就为:
X:

下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 0 1 0

Y:

下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 1 0 0
1.按位与
  • 描述:相同位的两个数字都为1,则为1,否则为0,C语言中是X&Y,得出的结果为:
下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 0 0 0

计算结果为:0(看到X第1位为1,Y第1位为0,所以算出的结果第1位为0,同理得算出的结果的第2位为0)

2.按位或
  • 描述:相同位只要有一个为1,则为1,否则为0,C语言中为X|Y,得出的结果为:
下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 1 1 0

算出的结果为:2^1+2^2 = 6 (X第1位为1,Y第1位为0,所以“或”之后得到结果第1位为1,同理第2位也为1)

3.按位异或
  • 描述:相同位不同则为1,相同则为0,C语言中为X^Y,得出的结果为:
下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 0 1 1 0

计算结果为:2^1+2^2 = 6 (X第1位为1,Y第1位为0,“异或”之后的结果第1位为1,同理第2位也为1,其他为0)

4.按位取反
  • 描述:对原位的0和1全部取反(要考虑有没有符号),C语言中为~X,得出的结果为:
下标 7 6 5 4 3 2 1 0
对应位 1 1 1 1 1 1 0 1

计算结果为:2^0+2^2+2^3+2^4+2^5+2^6+2^7 (不想算结果了,X中第1位为1,其他为0,所以取反后就是这个结果)

5.左移
  • 描述:X的位左移a位,相当于X*2^a,C语言中是X<<a,假如a是2,得出的结果是:
下标 7 6 5 4 3 2 1 0
对应位 0 0 0 0 1 0 0 0

计算结果为:2^3 = 8 (X中的位都左移2位,相当于2*2^2 = 8)

6.右移
  • 描述:X的位右移a位,相当于X/2^a(取整),C语言中是X>>a,结算的过程跟左移差不多,但是是右移的,就不算了.

三.Lua的bit库

lua的原生库中有对位运算的函数.

  • bit.band   “与”操作  X和Y都为1时则为1,否则为0
  • bit.rol   “左旋”
  • bit.rshift   “逻辑右移”
  • bit.lshift   “逻辑左移”
  • bit.ror   “右旋”
  • bit.bxor   “非”操作  X和Y不同则为1,否则为0
  • bit.bor   “或”操作  X和Y中有一个为1,则为1,否则为0
  • bit.arshift   “算术”右移
  • bit.bnot   “取反”操作
  • tobit   转成位格式
  • tohex   转出16进制格式

四.bit实践

  • 红点位记录
    • 问题描述:一个模块有一个总的红点显示,这个红点受其模块下的标签红点影响,比如模块A的有三个标签1、2、3,只要其中一个标签有红点,则模块A就会有红点.

    • 实现:初始化总红点all_red = 0,各个标签设为1,2,3,那么单个标签(假设标签为tab)设置红点的接口:
      • 有红点时:bit.bor(all_red, bit.lshift(1, tab)),再把最后的值给all_red
      • 无红点时:bit.band(all_red, bit.bnot(bit.lshift(1, tab))),再把最后的值给all_red
    • 使用:最后使用就是用于判断主模块红点以及各个标签的红点:
      • 判断主模块的红点:all_red > 0是否为true,为true则是有红点;
      • 判断各个标签的红点:bit.band(all_red, bit.lshift(1, tab)) ~= 0是否为true,为true则是单个标签有红点;
  • 战斗状态记录

五.链接

https://baike.baidu.com/item/%E4%BD%8D%E8%BF%90%E7%AE%97/6888804?fr=aladdin
http://c.biancheng.net/view/3299.html