位运算符 |
|
从 5.2 版本开始,Lua 附带了库 [bit32],它添加了对位运算的支持。Lua 的早期版本不包含位运算符,但 bit32 已被移植回 5.1 版本。或者,也有一些 Lua 库可以实现此功能,以及一些 Lua 的修补版本。
Lua 中位运算符的实现
int32_t
和 int64_t
lua_Number
类型上具有一致的语义。还定义了 LuaJIT 2 位运算语义。通常被认为是 Lua 中位运算的最佳实践。与 bitlib 类似的接口,但更新,旨在取代它 [2][3].
Op "bit" 的接口。bxor 实现类似于 Roberto 的。(DavidManura)
Op (版本 1.0.1) 描述
bit.tobit(x) -- normalize number to the numeric range of -- bit operations (all bit ops use this implicitly) bit.tohex(x[,n]) -- convert x to hex with n digits (default 8) bit.bnot(x) -- bitwise not of x bit.band(x1[,x2...]) -- bitwise and of x1, x2, ... bit.bor(x1[,x2...]) -- bitwise or of x1, x2, ... bit.bxor(x1[,x2...]) -- bitwise xor of x1, x2, ... bit.lshift(x, n) -- left-shift of x by n bits bit.rshift(x, n) -- logical right-shift of x by n bits bit.arshift(x, n) -- arithmetic right-shift of x by n bits bit.rol(x, n) -- left-rotate of x by n bits bit.ror(x, n) -- right-rotate of x by n bits bit.bswap(x) -- byte-swap of x (little-endian <-> big-endian)
bit.bits -- number of bits usable in bitwise operations bit.bnot(a) -- returns the one's complement of a bit.band(w1, ...) -- returns the bitwise and of the w's bit.bor(w1, ...) -- returns the bitwise or of the w's bit.bxor(w1, ...) -- returns the bitwise exclusive or of the w's bit.lshift(a, b) -- returns a shifted left b places bit.rshift(a, b) -- returns a shifted logically right b places bit.arshift(a, b) -- returns a shifted arithmetically right b places bit.cast(a) -- cast a to the internally-used integer type
bitlib 使用 C 语言实现。在内部,每个位数组都实现为一个整数类型。采用 MIT 许可证。
bits.create(value, number) -- return bitmap of given size set to value bits:set(value) -- set all bits to value, return bitmap bits:set(value, n1[,n2[n3,...]]) -- set these bits to value, return bitmap bits:get(n) -- get value of this bit bits:get(n1[,n2[n3,...]]) -- get value of these bits bits:iterator() -- return iterator for all bits => i,v bits:iterator(n) -- return iterator starting at bit n => i,v bits:iterator(n1, n2) -- return iterator over range [n1..n2] => i,v bits:index(value) -- return iterator => next index with the value bits:index(value, start) -- return index of next bit with the value bits:isequal(b) bits == b -- return true or false for equality bits:notbits() - bits -- return NOT of the bitmap bits:orbits(b) bits + b -- return OR of the bitmaps bits:andbits(b) bits * b -- return AND of the bitmaps bits:xorbits(b) bits % b -- return XOR of the bitmaps bits:orbits(n1, n2[, n3,...]) -- return OR of these bits bits:andbits(n1, n2[, n3,...]) -- return AND of these bits bits:xorbits(n1, n2[, n3,...]) -- return XOR of these bits bits:copy() -- return a copy of the bitmap bits:printlimit() -- return current limit bits:printlimit(n|"all"|"*") -- set n or all bits printed, return new limit bits:size(), #bits -- return the bit capacity bits:ones() -- return the number of 1 bits bits.version() -- return the version of module
function bit(p) return 2 ^ (p - 1) -- 1-based indexing end -- Typical call: if hasbit(x, bit(3)) then ... function hasbit(x, p) return x % (p + p) >= p end function setbit(x, p) return hasbit(x, p) and x or x + p end function clearbit(x, p) return hasbit(x, p) and x - p or x end
这更像是一种设计模式,而不是一个实际的库。它使用 Lua 语言实现。在内部,每个位数组都实现为一个 Lua 数字。上面的基本操作提供了简单的代码来测试/设置/清除数字中的位。位运算可以用这些函数来定义。
Bit (版本 0.4) 描述
bit.bnot(n) -- bitwise not (~n) bit.band(m, n) -- bitwise and (m & n) bit.bor(m, n) -- bitwise or (m | n) bit.bxor(m, n) -- bitwise xor (m ^ n) bit.brshift(n, bits) -- right shift (n >> bits) bit.blshift(n, bits) -- left shift (n << bits) bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
LuaBit 完全使用 Lua 语言实现。在内部,每个位数组都实现为一个 Lua 数字或一个 Lua 数字数组。此包还包括用于将数字转换为十六进制字符串或从十六进制字符串转换的函数,一个用于 UTF8 -> UCS2 字符串转换的 'utf8' 模块,以及一个与诺基亚 PC 相关的 'noki' 模块。采用 MIT 许可证。
Dec
Hex (2007-10) 描述
Hex2Bin(s) Bin2Hex(s) Hex2Dec(s) Dec2Hex(s) Bin2Dec(s) Dec2Bin(s [, num]) BMAnd(v, m) BMNAnd(v, m) BMOr(v, m) BMXOr(v, m) BMNot(v, m)
BinDec
Hex 完全使用 Lua 语言编写。在内部,每个位数组都实现为一个以大端序形式的 Lua 字符串。采用 BSD 许可证。
Utils 描述BitUtils 提供了一些完全使用 Lua 语言实现的代码片段。在内部,通常情况下,每个位数组都实现为一个 Lua 数字。
Infix bitwise operators for AND (&, __and), OR (|, __or), XOR (^^, __xor). Infix bitwise operators for SHIFT LEFT (<<, __shl) and SHIFT RIGHT (>>, __shr). Unary bitwise negation operator (~, __not). Infix arithmetic operator for INTEGER DIVISION (\, __intdiv). accepts both ~= and != for comparison.
这是作为 Lua 的补丁实现的。在内部,每个位数组都实现为一个 Lua 数字。运算符作为语法扩展和 VM 操作码提供(包括元方法)。
Lua 描述RiscLua,版本早于版本 6,使用十六进制字面量并具有位运算符,每个运算符都有一个相应的事件。
x&y __bit_and x|y __bit_or x^^y __bit_xor ~x __bit_not -- also has arithmetic shifts: x<<y __bit_lshift x>>y __bit_rshift
这是作为 Lua 的补丁实现的。在内部,每个位数组都实现为一个 Lua 数字。运算符作为语法扩展和 VM 操作码提供(包括元方法)。该补丁不是独立的,而是被整合到 RiscLua 中。
| & ^^ << >> ~ \\ !=
这是作为 Lua 的补丁实现的。在内部,每个位数组都实现为一个新的基本值类型 (type(x) == 'hex'
, LUA_THEX
),不同于 'number'。此类型本身在内部是一个无符号整数。运算符作为语法扩展和 VM 操作码提供(包括元方法)。
-- example local a1= enum.new( 0x10, "I'm A" ) assert( tonumber(a1)==16 ) assert( tostring(a1)=="0x10" ) assert( tonumber(a1"not")==4294967279 ) assert( tostring(a1"not")=="0xffffffef" ) local c1= enum.new( 10 ) -- I'm None! assert( c1[3] == 1 ) -- 10 == 0x1010: bit 3 _is_ set
这是作为 Lua 的补丁实现的。在内部,每个位数组都实现为一个新的基本值类型 (type()
返回两个值:“enum” 和枚举族名称)。枚举值对 []
和 ()
运算符进行了重载,用于在 Lua 端执行按位运算。
上面的实现对两个问题处理方式不同(或在某些情况下根本不处理):
其中一个实现假设一个 32 位整数,并提供有符号和无符号右移运算。
另一个使用 long long
和 unsigned long long
,并依赖 C 编译器在每种情况下正确执行右移运算(它恰好适用于我在 x86 上使用 gcc 的情况,但 C89 和 C99 没有指定如何执行有符号右移运算;它是“实现定义的行为”)。
第三个似乎完全忽略了这个问题,并给我们提供了 C 编译器对 lua_Integer
的决定。
请注意,在添加运算符时,Java 将 >>
运算符定义为使用符号扩展,并将 >>>
运算符定义为使用零扩展。
它们似乎都没有提供一种可移植的方式将任意大小的位字段转换为有符号数字。
[这个] 补丁将非常棒,如果 bitfield
接受另一个可选的布尔参数来指示结果是否应该被符号扩展到 lua_Integer
的完整大小。
顺便说一句,一种无分支的方式来符号扩展位字段(Henry S. Warren Jr.,CACM v20 n6 1977 年 6 月)是:
sext = 1 << (len - 1); i = (i ^ sext) - sext;
i
是右对齐的,并且字段左侧的所有位都为零;这是上面补丁中需要此功能的情况(其中 sextp
是指示是否需要符号扩展的可选参数)
if (len < LI_BITS) { i &= LI_MASK(len); if (sextp) { lua_Integer sext = 1 << (len - 1); i = (i ^ sext) - sext; } }
至少有两个非常不同的原因导致按位运算:(1) 对一小部分成员进行集合运算,以及 (2) 对在 Lua 程序外部定义的数据的显式表示中的字段进行操作。引用的按位运算符实现主要针对后者。有关前者的实现,请参见 Asko 在 LuaPowerPatches 中的枚举/位运算补丁。
以下是一些使用位运算符的 Lua 代码示例(用例)
典型用途包括
对于一种旨在与 C/C++ 交互的语言来说,位运算符不属于语法的一部分很奇怪。当然,它们可以作为函数实现 - 但这很笨拙。请参阅 FeatureProposals。
“如何执行位运算?”是一个 LuaFaq 问题。
注意:十六进制字面量在 Lua 5.1 中添加:0xfe。
Java 有一个位向量的抽象,称为 EnumSet
[1]。Lua 上也可以做类似的事情。