Lua 运算符的完整指南

在 Lua 中,运算符是构建表达式的基础元素,其设计简洁但功能强大。以下是 Lua 运算符的完整指南,涵盖基础用法、进阶技巧及性能优化策略:



一、基础运算符详解

1. 算术运算符

运算符 描述 示例 注意事项
+ 加法 3 + 5 表与表相加会报错
- 减法 10 - 4 支持负数
* 乘法 2 * 6 矩阵乘法需自定义实现
/ 除法(浮点结果) 5 / 22.5 除以零返回 inf-inf
% 取模 7 % 31 负数取模规则与数学一致
^ 幂运算 2^38 右结合(2^3^22^(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 < 3false 支持字符串字典序比较
> 大于 "b" > "a"true
<= 小于等于 3 <= 3true
>= 大于等于 "a" >= "a"true

注意:
tableuserdata 只能用 ==/~=,无法直接比较内容。
NaN 与任何值(包括自身)比较均为 false


3. 逻辑运算符

运算符 描述 短路求值 示例
and 逻辑与(返回第一个假值) a and b → 若 a 为假则返回 a
or 逻辑或(返回第一个真值) a or b → 若 a 为真则返回 a
not 逻辑非 not truefalse

应用场景:

-- 默认值赋值
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 & 31
` ` 按位或
~ 按位异或 5 ~ 36
<< 左移 1 << 38
>> 右移 8 >> 22
~ 一元按位非 ~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 运算符的特性和底层机制,可以编写出更高效、健壮的代码。对于复杂场景,建议结合元表和自定义函数扩展运算符的语义。


猜你喜欢

转载自blog.csdn.net/qq_45657541/article/details/147099325
今日推荐