在 Lua 中,运算符是构建表达式的基础元素,其设计简洁但功能强大。以下是 Lua 运算符的完整指南,涵盖基础用法、进阶技巧及性能优化策略:
Lua 运算符的完整指南—目录
一、基础运算符详解
1. 算术运算符
运算符 | 描述 | 示例 | 注意事项 |
---|---|---|---|
+ |
加法 | 3 + 5 |
表与表相加会报错 |
- |
减法 | 10 - 4 |
支持负数 |
* |
乘法 | 2 * 6 |
矩阵乘法需自定义实现 |
/ |
除法(浮点结果) | 5 / 2 → 2.5 |
除以零返回 inf 或 -inf |
% |
取模 | 7 % 3 → 1 |
负数取模规则与数学一致 |
^ |
幂运算 | 2^3 → 8 |
右结合(2^3^2 → 2^(3^2) ) |
示例:
local a = 10
print(a / 3) -- 3.3333333333333
print(a ^ 0.5) -- 3.1622776601684 (sqrt(10))
2. 比较运算符
运算符 | 描述 | 示例 | 特殊规则 |
---|---|---|---|
== |
相等(深度比较) | {1} == {1} → false |
表需完全相同引用才相等 |
~= |
不等于 | "a" ~= "A" |
不同类型默认不等 |
< |
小于 | 5 < 3 → false |
支持字符串字典序比较 |
> |
大于 | "b" > "a" → true |
|
<= |
小于等于 | 3 <= 3 → true |
|
>= |
大于等于 | "a" >= "a" → true |
注意:
• table
和 userdata
只能用 ==
/~=
,无法直接比较内容。
• NaN
与任何值(包括自身)比较均为 false
。
3. 逻辑运算符
运算符 | 描述 | 短路求值 | 示例 |
---|---|---|---|
and |
逻辑与(返回第一个假值) | 是 | a and b → 若 a 为假则返回 a |
or |
逻辑或(返回第一个真值) | 是 | a or b → 若 a 为真则返回 a |
not |
逻辑非 | 否 | not true → false |
应用场景:
-- 默认值赋值
local value = input or "default"
-- 条件简化
if a and b then ... end -- 等价于 if a ~= nil and a ~= false and b ~= nil and b ~= false then ...
4. 位运算符(Lua 5.3+)
运算符 | 描述 | 示例 |
---|---|---|
& |
按位与 | 5 & 3 → 1 |
` | ` | 按位或 |
~ |
按位异或 | 5 ~ 3 → 6 |
<< |
左移 | 1 << 3 → 8 |
>> |
右移 | 8 >> 2 → 2 |
~ |
一元按位非 | ~5 → -6 |
注意: 位运算仅作用于整数,负数使用补码表示。
5. 字符串连接运算符
运算符 | 描述 | 示例 |
---|---|---|
.. |
字符串拼接 | "Hello " .. "World" → "Hello World" |
注意: ..
的优先级低于算术运算符,需注意括号:
print(1 .. 2 + 3) -- "15"(等价于 1 .. (2+3))
6. 长度运算符
运算符 | 描述 | 示例 |
---|---|---|
# |
获取表长度或字符串长度 | #{"a","b"} → 2 |
注意:
• 对于非数组表(有空洞的表),#
返回第一个 nil
前的索引。
• 字符串长度单位为字节(非字符数,UTF-8 下可能不准确)。
二、进阶用法与技巧
1. 运算符重载(模拟)
Lua 不支持运算符重载,但可通过元表 __add
等实现类似效果:
local complex = {
a = 1,
b = 2
}
local mt = {
__add = function(c1, c2)
return {
a = c1.a + c2.a, b = c1.b + c2.b}
end
}
setmetatable(complex, mt)
local result = complex + {
a=3, b=4} -- {a=4, b=6}
2. 隐式类型转换
Lua 在比较时会进行隐式类型转换:
print(1 == "1") -- false(严格比较)
print(1 + "2") -- 3(字符串 "2" 转为数字)
print(nil == false) -- false(nil 与布尔值互不相等)
3. 短路求值优化
利用 and
/or
的短路特性实现条件控制:
-- 安全获取嵌套表字段
local value = obj and obj.data and obj.data.value
-- 实现三元运算符
local function ternary(cond, true_val, false_val)
return cond and true_val or false_val
end
print(ternary(5 > 3, "Yes", "No")) -- 输出 "Yes"
三、性能优化指南
1. 减少全局查找
将频繁使用的运算符相关函数或表缓存为局部变量:
local string_len = string.len
for i = 1, 1e6 do
local len = string_len("hello") -- 比直接调用快约 30%
end
2. 避免重复计算
预计算可复用的值:
-- 低效写法
for i = 1, 100 do
print(math.sqrt(i) + math.sqrt(i)) -- 两次计算 sqrt(i)
end
-- 优化写法
for i = 1, 100 do
local s = math.sqrt(i)
print(s + s)
end
3. 位运算替代乘除法
在特定场景下用位移加速计算:
-- 快速乘以 8
local x = 5
local fast_mul = x << 3 -- 等价于 x * 8
-- 快速除以 4
local fast_div = x >> 2 -- 等价于 math.floor(x / 4)
4. 表连接优化
避免频繁使用 ..
拼接大字符串:
-- 低效写法
local result = ""
for i = 1, 1000 do
result = result .. tostring(i)
end
-- 高效写法(使用表缓冲)
local buffer = {
}
for i = 1, 1000 do
table.insert(buffer, tostring(i))
end
local result = table.concat(buffer)
四、常见陷阱与解决方案
1. ==
比较陷阱
local a = {
x=1}
local b = {
x=1}
print(a == b) -- false(不同表对象)
-- 解决方案:深度比较函数
local function deep_equal(t1, t2)
return t1 == t2 or (type(t1) == "table" and type(t2) == "table" and
next(t1) == next(t2)) -- 简单递归实现需完善
end
2. ^
运算符优先级问题
print(2^3^2) -- 2^(3^2) = 512,而非 (2^3)^2 = 64
3. 浮点数精度丢失
local a = 0.1 + 0.2
print(a) -- 0.30000000000000004
print(a == 0.3) -- false
-- 解决方案:使用整数运算或精度库
local function round(num, decimals)
local factor = 10^decimals
return math.floor(num * factor + 0.5) / factor
end
print(round(0.1 + 0.2, 2)) -- 0.3
五、运算符优先级表
优先级 | 运算符 | 描述 |
---|---|---|
1 | ^ |
幂运算(右结合) |
2 | not , # , - |
单目运算符 |
3 | * , / , % |
乘除取模 |
4 | + , - |
加减 |
5 | .. |
字符串连接 |
6 | == , ~= , < , > , <= , >= |
比较运算符 |
7 | and |
逻辑与 |
8 | or |
逻辑或 |
六、实战示例
示例1:快速排序实现(利用比较运算符)
local function quicksort(t)
if #t <= 1 then return t end
local pivot = t[math.random(#t)]
local left, right = {
}, {
}
for _, v in ipairs(t) do
if v < pivot then
table.insert(left, v)
elseif v > pivot then
table.insert(right, v)
end
end
return quicksort(left)..quicksort(right)
end
local arr = {
3,6,8,10,1,2,1}
print(table.unpack(quicksort(arr))) -- 输出 1 1 2 3 6 8 10
示例2:位运算实现快速乘法
local function multiply(a, b)
local res = 0
while b > 0 do
if b & 1 ~= 0 then
res = res + a
end
a = a << 1
b = b >> 1
end
return res
end
print(multiply(5, 3)) -- 15
通过深入理解 Lua 运算符的特性和底层机制,可以编写出更高效、健壮的代码。对于复杂场景,建议结合元表和自定义函数扩展运算符的语义。