运算符详解

4.1 算术运算符

运算符 含义 示例 结果
+ 加法 10 + 3 13
- 减法 10 - 3 7
* 乘法 10 * 3 30
/ 除法 10 / 3 3.3333
// 整除(5.3+) 10 // 3 3
% 取模 10 % 3 1
^ 幂运算 2 ^ 10 1024
- 负号 -5 -5

除法与整除

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 普通除法总是返回浮点数
print(10 / 3) --> 3.3333333333333
print(10 / 2) --> 5.0(注意结果是浮点)

-- 整除 // 返回商(向负无穷取整)
print(10 // 3) --> 3
print(-10 // 3) --> -4(因为 3 * -4 = -12 ≤ -10)
print(10 // -3) --> -4
print(-10 // -3) --> 3

-- 整除等价于 floor division
-- math.floor(10 / 3) = 3
-- math.floor(-10 / 3) = -4

取模运算

取模运算满足公式:a % b == a - ((a // b) * b)

1
2
3
4
5
6
7
8
9
10
11
12
print(10 % 3)           --> 1
print(-10 % 3) --> 2
print(10 % -3) --> -2
print(-10 % -3) --> -1

-- 用途举例:判断奇偶
local function is_even(n)
return n % 2 == 0
end

-- 用途举例:限制范围(时钟时间)
local hour = (current_hour % 12)

幂运算

1
2
3
4
print(2 ^ 3)            --> 8.0
print(2 ^ 0.5) --> 1.4142135623731(平方根)
print(10 ^ -2) --> 0.01
print(16 ^ (1/4)) --> 2.0(四次方根)

浮点数精度

1
2
3
4
5
6
7
8
-- 浮点数比较可能出问题
print(0.1 + 0.2 == 0.3) --> false(经典浮点精度问题)

-- 正确比较方式
local function approx_eq(a, b, epsilon)
return math.abs(a - b) < (epsilon or 1e-10)
end
print(approx_eq(0.1 + 0.2, 0.3)) --> true

4.2 关系运算符

运算符 含义 示例 结果
== 等于 5 == 5 true
~= 不等于 5 ~= 3 true
< 小于 3 < 5 true
> 大于 5 > 3 true
<= 小于等于 5 <= 5 true
>= 大于等于 5 >= 3 true

比较规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- 数值比较
print(10 > 5) --> true
print(10 >= 10) --> true

-- 字符串比较(按字母顺序)
print("apple" < "banana") --> true
print("Apple" < "apple") --> true(大写字母 ASCII 小于小写)

-- 不同类型比较
print(10 == "10") --> false(不自动转型)
print(10 == 10.0) --> true(数字不区分整数浮点)

-- table/function 比较:按引用
local a = {1, 2}
local b = {1, 2}
local c = a
print(a == b) --> false(内容相同但引用不同)
print(a == c) --> true(同一引用)

记住:Lua 中 == 用于相等判断,~= 用于不等判断。没有 ===(严格等于),因为不会发生类型转换。


4.3 逻辑运算符

运算符 含义 说明
and 逻辑与 短路求值
or 逻辑或 短路求值
not 逻辑非 取反

短路求值机制

and 如果第一个操作数为假,返回第一个操作数;否则返回第二个操作数。

or 如果第一个操作数为真,返回第一个操作数;否则返回第二个操作数。

1
2
3
4
5
6
7
8
9
10
-- and 短路
print(false and error("不会执行")) --> false
print(nil and 100) --> nil
print(true and 200) --> 200
print(0 and "真") --> "真"(0 在 Lua 中为真)

-- or 短路
print(true or error("不会执行")) --> true
print(false or "默认值") --> "默认值"
print(nil or 100) --> 100

常见用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- 设置默认值(最常用)
local name = input_name or "匿名"

-- 等同于:
if input_name then
name = input_name
else
name = "匿名"
end

-- 多条件选择
local function get_greeting(hour)
return (hour < 12 and "上午好") or (hour < 18 and "下午好") or "晚上好"
end

print(get_greeting(9)) --> 上午好
print(get_greeting(14)) --> 下午好
print(get_greeting(20)) --> 晚上好

-- 守卫模式(guard)
local function safe_div(a, b)
return b ~= 0 and a / b or nil -- b 为 0 时返回 nil
end

print(safe_div(10, 2)) --> 5
print(safe_div(10, 0)) --> nil

not 运算符

1
2
3
4
5
6
print(not true)         --> false
print(not false) --> true
print(not nil) --> true
print(not 0) --> false(0 为真)
print(not "") --> false(空字符串也为真)
print(not not 42) --> true(双取反转为 boolean)

4.4 字符串连接运算符 ..

字符串连接使用两个点 ..不是 +

1
2
3
4
5
6
7
8
9
10
11
12
13
local s = "Hello" .. " " .. "World"
print(s) --> Hello World

-- 数字自动转换为字符串
print("年龄:" .. 30) --> 年龄:30

-- 注意:连接操作创建新字符串(字符串不可变)
local a = "abc"
local b = a .. "def"
print(a) --> abc(原字符串不变)
print(b) --> abcdef(新字符串)

-- 连接大量字符串时性能要注意(后面章节会讲 table.concat)

4.5 长度运算符 #

长度运算符返回字符串或数组的长度:

字符串长度

1
2
3
4
5
6
print(#"hello")         --> 5
print(#"") --> 0

-- 中文字符:UTF-8 情况下一个汉字占 3 个字节
print(#"你好") --> 6(字节数,不是字符数)
print(#"Lua入门") --> 9(3 + 3 + 3)

数组(表)长度

1
2
3
4
5
6
7
8
9
10
11
local arr = {10, 20, 30}
print(#arr) --> 3

-- 空洞问题:如果中间有 nil,结果不可靠
local t = {1, nil, 3}
print(#t) --> 可能是 1 或 3(未定义行为)
-- 实际结果取决于 nil 的位置,不建议对含空洞的数组用 #

-- 字典部分不计入长度
local mix = {1, 2, 3, key = "value"}
print(#mix) --> 3(只计算整数索引部分)

4.6 运算符优先级

从高到低:

优先级 运算符
1(最高) ^
2 -(负号) # not
3 * / // %
4 + -(减法)
5 ..(连接)
6 < > <= >= == ~=
7 and
8(最低) or
1
2
3
4
5
6
7
8
9
-- 示例解释
print(2 + 3 * 4) --> 14(* 优先于 +)
print((2 + 3) * 4) --> 20(括号改变优先级)
print(2 ^ 3 * 4) --> 32(^ 优先于 *,即 (2^3)*4)
print(not true and false) --> false(not 优先于 and)
print(true or false and false) --> true(and 优先于 or)

-- 括号是最安全的方式
result = ((a + b) * c) / (d - e)

4.7 本章小结

类别 运算符
算术 + - * / // % ^
关系 == ~= < > <= >=
逻辑 and or not
其他 ..(连接) #(长度)
赋值 =(不是运算符,是语句)

练习题

  1. 计算 ((5 + 3) * 2 ^ 3 - 10) % 7 的结果
  2. 利用 or 运算符为函数参数提供默认值
  3. 实现一个函数,判断年份是否为闰年(能被 4 整除但不能被 100 整除,或者能被 400 整除)
  4. 使用 # 运算符计算任意字符串的长度,并测试中文字符串
  5. andor 实现三目运算符:max = (a > b) and a or b
ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
Lua基础教程 系列
第 4/15 篇
分享: