一、位运算
从 Lua 5.3 版本开始,提供了针对数值类型的一组标准位运算符,与算数运算符不同的是,运算符只能用于整型数。
运算符 | 描述 |
---|---|
& | 按位与 |
| | 按位或 |
~ | 按位异或 |
>> | 逻辑右移 |
<< | 逻辑左移 |
~(一元运算) | 按位取反 |
位的使用,可以参考小盆友的另一篇文章 《android位运算简单讲解》
https://blog.csdn.net/weixin_37625173/article/details/83796580
print(string.format("%x", 0xff & 0xabcd)) --> cd
print(string.format("%x", 0xff | 0xabcd)) --> abff
print(string.format("%x", 0xff ~ 0xabcd)) --> ab32
print(string.format("%x", ~0)) --> ffffffffffffffff (16 个 6,每一个十六进制 4 位,刚好是 64 位)
print(string.format("%x", 0xff << 12)) --> ff000
print(string.format("%x", 0xff >> -12)) --> ff000
-- 移位数等于或大于整型表示的位数,由于所有的位都被移出,则结果为 0
print(string.format("%x", -1 << 80)) --> 0
1-1、注意小点
所有的位运算针对一个整数型的所有位。
Lua 的两个移位操作都会用 0 填充空出的位,这种行为称为逻辑移位。 Lua 中没有提供算术右移(即使用符号位填充空出的位),但是可以通过向下取整除法( floor 除法)达到算数右移
local data = -0x100
print("逻辑右移:", string.format("%x >> 1 --> %x", data, data >> 1)) --> 逻辑右移: ffffffffffffff00 >> 1 --> 7fffffffffffff80
-- 达到算数右移一位,2^n ( n 即为右移位数)
print("算数右移:", string.format("%x >> 1 --> %x", data, data // 2)) --> 算数右移: ffffffffffffff00 >> 1 --> ffffffffffffff80
移位数是负数则表示向相反方向移位。a>>n
和 a<<-n
相等。
二、无符号整型数
在有符号整型数中使用一个比特位来存储符号位。所以 64 的整型数中最大可以表示为 2^63-1 ,而不是 2^64-1 。
值得注意的是 Lua 语言不显示支持无符号整型数, 但这并不妨碍我们在 Lua 中使用无符号整型这一特性,只是在使用过程中需要注意一些细节。
2-1、细节一:打印无符号整数
对于一个数最直观的就是展示出来,所以我们可以使用 string.format
进行格式化数值, 使用 %u
(无符号整数)或 %X
(十六进制)进行展示,这样就能很直观的感知无符号整数每一位的数值是多少。如果直接将无符号整数打印,会被认为是有符号整数,就不利于阅读。
local x = 3 << 62
print("有符号整数显示:", x) --> 有符号整数显示: -4611686018427387904
print("使用十进制无符号显示", string.format("%u", x)) --> 使用十进制无符号显示 13835058055282163712
print("使用十六进制无符号显示", string.format("0x%X", x)) --> 使用十六进制无符号显示 0xC000000000000000
2-2、细节二:无符号整数,加减乘运算
对于无符号整数的加减乘运算,和有符号是一样的,只是要注意溢出
local x = 3 << 62
print("使用十进制无符号显示", string.format("%u", x)) --> 使用十进制无符号显示 13835058055282163712
print("使用十进制无符号显示 +1", string.format("%u", x + 1)) --> 使用十进制无符号显示 +1 13835058055282163713
print("使用十进制无符号显示 -1", string.format("%u", x - 1)) --> 使用十进制无符号显示 -1 13835058055282163711
x = 1 << 62
print("使用十六进制无符号显示", string.format("0x%X", x)) --> 使用十六进制无符号显示 0x4000000000000000
print("使用十进制无符号显示 * 2", string.format("%X", x * 2)) --> 使用十进制无符号显示 * 2 0x8000000000000000
2-3、细节三:无符号整数,除法运算
对于无符号整数的除法会有些不一样,需要注意其符号位的影响,可以通过下面函数进行无符号整数的除法(细节也在每一行的注释中)
function udiv(n, d)
-- d<0 实