运算符 Lua 运算符详解:代码实践与应用指南 1. 运算符概述 运算符是编程语言中用于执行特定操作的符号。它们作用于一个或多个操作数(operand),并产生一个结果。Lua 作为一种轻量级、高效的脚本语言,提供了丰富的运算符,涵盖了算术运算、关系比较、逻辑运算、字符串操作、位运算等多个方面。 掌握 Lua 运算符是编写 Lua 代码的基础。它们如同积木,通过灵活组合,可以构建出复杂的功能逻辑。理解运算符的优先级、结合性以及不同数据类型之间的运算规则,能够帮助开发者避免常见的错误,并编写出更健壮、可维护的代码。 2. 算术运算符 算术运算符用于执行基本的数学计算。
1. 运算符概述
运算符是编程语言中用于执行特定操作的符号。它们作用于一个或多个操作数(operand),并产生一个结果。Lua 作为一种轻量级、高效的脚本语言,提供了丰富的运算符,涵盖了算术运算、关系比较、逻辑运算、字符串操作、位运算等多个方面。
掌握 Lua 运算符是编写 Lua 代码的基础。它们如同积木,通过灵活组合,可以构建出复杂的功能逻辑。理解运算符的优先级、结合性以及不同数据类型之间的运算规则,能够帮助开发者避免常见的错误,并编写出更健壮、可维护的代码。
2. 算术运算符
算术运算符用于执行基本的数学计算。Lua 提供了以下算术运算符:
| 运算符 | 名称 | 描述 | 代码示例及详解 |
|---|---|---|---|
+ |
加法 | 两个操作数相加 | lua print(5 + 3) -- 输出 8 print(10.5 + 2.5) -- 输出 13.0 |
* |
乘法 | 两个操作数相乘 | lua print(6 * 7) -- 输出 42 print(2.5 * 4) -- 输出 10.0 |
// |
整除 | 第一个操作数除以第二个操作数,结果向下取整(Lua 5.3+) | lua print(15 // 3) -- 输出 5 print(10 // 3) -- 输出 3 print(-10 // 3) -- 输出 -4 |
^ |
指数 | 返回第一个操作数的第二个操作数次幂 | lua print(2 ^ 3) -- 输出 8 print(5 ^ 0.5) -- 输出 2.2360679774998 |
代码实践 1:简单的计算器
-- 简单的计算器程序 print("请输入两个数字和运算符 (+, -, *, /, //, %, ^):") local num1 = tonumber(io.read()) local operator = io.read() local num2 = tonumber(io.read()) if num1 and operator and num2 then local result if operator == "+" then result = num1 + num2 elseif operator == "-" then result = num1 - num2 elseif operator == "*" then result = num1 * num2 elseif operator == "/" then result = num1 / num2 elseif operator == "//" then result = num1 // num2 elseif operator == "%" then result = num1 % num2 elseif operator == "^" then result = num1 ^ num2 else print("无效的运算符!") return end print("结果:", result) else print("输入无效!请确保输入的是数字和运算符。") end
代码详解 1:
这段代码演示了算术运算符的基本用法。
io.read() 用于从控制台读取用户输入。
tonumber() 将用户输入的字符串转换为数字。
if-elseif-else 结构根据用户输入的运算符执行相应的算术运算。
print() 函数用于输出结果。
3. 关系运算符
关系运算符用于比较两个操作数之间的关系,并返回一个布尔值(true 或 false)。Lua 提供了以下关系运算符:
| 运算符 | 名称 | 描述 | 代码示例及详解 |
|---|---|---|---|
== |
等于 | 检查两个操作数是否相等 | lua print(5 == 5) -- 输出 true print(5 == 6) -- 输出 false print("hello" == "hello") -- 输出 true print(5 == "5") -- 输出 false (类型不同) |
< |
小于 | 检查第一个操作数是否小于第二个操作数 | lua print(5 < 10) -- 输出 true print(10 < 5) -- 输出 false |
<= |
小于等于 | 检查第一个操作数是否小于或等于第二个操作数 | lua print(5 <= 5) -- 输出 true print(5 <= 6) -- 输出 true print(6 <= 5) -- 输出 false |
代码实践 2:比较大小
-- 比较两个数字的大小 print("请输入两个数字:") local num1 = tonumber(io.read()) local num2 = tonumber(io.read()) if num1 and num2 then if num1 == num2 then print("两个数字相等。") elseif num1 < num2 then print(num1, "小于", num2) else print(num1, "大于", num2) end else print("输入无效!请确保输入的是数字。") end
代码详解 2:
这段代码演示了关系运算符用于比较数字大小。
if-elseif-else 结构根据关系运算符的结果执行不同的分支。
关系运算符的结果 (true 或 false) 直接用于条件判断。
注意:
Lua 中 == 和 ~= 运算符会比较值和类型。如果类型不同,即使值看起来相似,结果也可能为 false。例如 5 == "5" 返回 false。
对于字符串的比较,关系运算符按照字典顺序进行比较。
4. 逻辑运算符
逻辑运算符用于组合或修改布尔值,返回一个新的布尔值。Lua 提供了以下逻辑运算符:
| 运算符 | 名称 | 描述 | 代码示例及详解 |
|---|---|---|---|
and |
逻辑与 | 如果两个操作数都为真,则返回真,否则返回假。短路求值:如果第一个操作数为假,则直接返回假,不再计算第二个操作数。 | lua print(true and true) -- 输出 true print(true and false) -- 输出 false print(false and true) -- 输出 false print(false and false) -- 输出 false print(nil and 10) -- 输出 nil (nil 视为假) print(false and error("不会执行")) -- 输出 false (短路求值) |
not |
逻辑非 | 对操作数取反。如果操作数为真,则返回假,如果操作数为假,则返回真。 | lua print(not true) -- 输出 false print(not false) -- 输出 true print(not nil) -- 输出 true (nil 视为假) print(not 0) -- 输出 false (0 视为真) |
| 代码实践 3:用户权限验证 |
-- 用户权限验证 local isAdmin = false local isLoggedIn = true if isLoggedIn and isAdmin then print("欢迎管理员!") elseif isLoggedIn then print("欢迎普通用户!") else print("请先登录!") end -- 使用 or 的默认值设置 local username = io.read() or "guest" -- 如果用户没有输入,则默认为 "guest" print("用户名:", username)
代码详解 3:
if-elseif-else 结构使用 and 运算符组合了两个条件 (isLoggedIn 和 isAdmin),用于判断用户权限。or 运算符在第二个例子中用于设置默认值。如果 io.read() 返回 nil (用户没有输入),则 username 被赋值为 "guest"。and 和 or 不仅仅返回布尔值 true 或 false。
and:如果第一个操作数为假(false 或 nil),则返回第一个操作数;否则返回第二个操作数。or:如果第一个操作数为真(除了 false 和 nil 的任何值),则返回第一个操作数;否则返回第二个操作数。false 和 nil 被视为假,其他任何值(包括 0 和空字符串 "")都被视为真。.. | 连接 | 将两个字符串连接起来,生成一个新的字符串 | lua print("hello" .. " " .. "world") -- 输出 hello world local name = "Lua" print("Language: " .. name) -- 输出 Language: Lua |# | 长度 | 返回字符串的长度(字节数) | lua print(#"hello") -- 输出 5 print(#"你好") -- 输出 6 (UTF-8 编码,每个汉字通常占 3 个字节) |-- 字符串拼接和长度计算 local firstName = "John" local lastName = "Doe" local fullName = firstName .. " " .. lastName print("姓名:", fullName) print("姓名长度:", #fullName) local message = "欢迎来到 Lua 世界!" print("消息:", message) print("消息长度:", #message)
代码详解 4:
.. 运算符用于将 firstName、空格和 lastName 连接成完整的姓名 fullName。# 运算符用于获取字符串 fullName 和 message 的长度。.. 每次都会创建一个新的字符串对象。# 运算符返回的是字符串的字节数,而不是字符数。对于多字节字符编码(如 UTF-8),一个字符可能占用多个字节。=:= | 赋值 | 将右侧操作数的值赋给左侧的操作数(变量) | lua local x = 10 local name = "Alice" local isReady = true |Lua 中没有像 C/C++/Java 等语言中常见的复合赋值运算符(如 +=, -=, *=, /=, %= 等)。 你需要使用简单的赋值运算符和算术运算符来达到相同的效果:
local count = 5 count = count + 1 -- 相当于 count += 1 print(count) -- 输出 6 local price = 20 price = price * 0.9 -- 相当于 price *= 0.9 (打九折) print(price) -- 输出 18.0
7. 位运算符 (Lua 5.3+)
位运算符用于对整数类型的二进制位进行操作。Lua 5.3 及以上版本提供了位运算符:
| 运算符 | 名称 | 描述 | 代码示例及详解 |
|---|---|---|---|
& |
按位与 | 如果两个操作数的对应位都为 1,则该位结果为 1,否则为 0。 | lua print(5 & 3) -- 输出 1 (二进制: 0101 & 0011 = 0001) |
~ |
按位异或 | 如果两个操作数的对应位不同,则该位结果为 1,否则为 0。 | lua print(5 ~ 3) -- 输出 6 (二进制: 0101 ~ 0011 = 0110) |
<< |
左移 | 将第一个操作数的二进制位向左移动第二个操作数指定的位数,右侧空出的位用 0 填充(逻辑左移)。 | lua print(2 << 3) -- 输出 16 (二进制: 0010 << 3 = 10000) |
~~ |
按位取反 | 对操作数的每一位取反(0 变为 1,1 变为 0)。 | lua print(~~5) -- 输出 -6 (二进制: ~0101 = ...1010,补码表示,十进制 -6) |
| 代码实践 5:位运算示例 |
-- 位运算示例 local a = 5 -- 二进制: 0101 local b = 3 -- 二进制: 0011 print("a & b (按位与):", a & b) print("a | b (按位或):", a | b) print("a ~ b (按位异或):", a ~ b) print("a << 1 (左移一位):", a << 1) print("a >> 1 (右移一位):", a >> 1) print("~a (按位取反):", ~~a) -- 使用位运算进行权限控制示例 local READ_PERMISSION = 1 -- 二进制: 0001 local WRITE_PERMISSION = 2 -- 二进制: 0010 local EXECUTE_PERMISSION = 4 -- 二进制: 0100 local userPermissions = READ_PERMISSION | EXECUTE_PERMISSION -- 用户拥有读和执行权限 (二进制: 0101) -- 检查用户是否拥有写权限 if (userPermissions & WRITE_PERMISSION) ~= 0 then print("用户拥有写权限") else print("用户没有写权限") end -- 检查用户是否拥有读权限 if (userPermissions & READ_PERMISSION) ~= 0 then print("用户拥有读权限") else print("用户没有读权限") end
代码详解 5:
# | 长度运算符 | 除了用于字符串,# 运算符还可以用于获取 table 的长度(仅限序列式 table,即从索引 1 开始连续的 table)。 | lua local str = "hello" print(#str) -- 输出 5 local arr = {10, 20, 30, 40} print(#arr) -- 输出 4 local mixedTable = {a = 1, b = 2, [1] = 10, [2] = 20} print(#mixedTable) -- 输出 2 (只计算序列部分) local emptyTable = {} print(#emptyTable) -- 输出 0 |() | 函数调用运算符 | 用于调用函数。 | lua function add(a, b) return a + b end print(add(3, 5)) -- 输出 8 || [] | 索引运算符 | 用于访问 table 中的元素。 | lua local myTable = {name = "Lua", version = 5.4} print(myTable["name"]) -- 输出 Lua print(myTable.version) -- 输出 5.4 (语法糖,等价于 myTable["version"]) local arr = {10, 20, 30} print(arr[1]) -- 输出 10 (Lua table 索引从 1 开始) |: | 方法调用运算符 | 用于调用 table 中存储的函数(方法),并将 table 自身作为第一个参数 self 传递给函数。(语法糖) | lua local myObject = { name = "Object", greet = function(self) print("Hello from " .. self.name) end } myObject:greet() -- 输出 Hello from Object (等价于 myObject.greet(myObject)) || ... | 可变参数运算符 | 在函数定义中,... 表示函数可以接受可变数量的参数。在函数调用中,... 可以用于展开 table 或其他可迭代对象作为参数。 | lua function varargFunc(...) local args = {...} -- 将可变参数收集到 table 中 for i, v in ipairs(args) do print("参数", i, ":", v) end end varargFunc(1, 2, "hello") -- 输出 参数 1 : 1 参数 2 : 2 参数 3 : hello local numbers = {10, 20, 30} varargFunc(unpack(numbers)) -- Lua 5.1+ (Lua 5.2+ 可以直接 varargFunc(table.unpack(numbers)) ) -- 输出 参数 1 : 10 参数 2 : 20 参数 3 : 30 |