3.6 运算
Lua里的运算有算术运算、关系运算、逻辑运算、字符串运算等。
3.6.1 算术运算
Lua的算术运算包括基本的加减乘除,取模运算使用“%”,幂运算使用“^”:
print(1 + 1, ", ", 5-3) -- 加减法运算,输出2,2 print(2 * 4, ", ", 1 / 3) -- 乘除法运算,输出8,0.33333333333333 print(5 % 2, ", ", 3 ^ 3) -- 取模和幂运算,输出1,27
算术运算时可以混用字符串类型,Lua会自动把字符串转换为数字,但如果含有非数字字符无法转换就会出错,所以最好不要混用。
Lua不提供其他语言里的递增和递减操作符(可能的原因是“--”已经被用作注释语法了),递增递减操作只能使用标准的赋值形式,例如:
count = 10 -- 一个整数变量 count = count + 1 -- 加1后赋值,相当于++count
3.6.2 关系运算
Lua的关系运算符与其他语言基本相同,如“>”“>=”“<”“<=”“==”,但不等比较使用的是“~=”,需要特别注意:
print(3.14 > 2.718) -- 大于关系 print(1/3 == 2/6) -- 等于关系 print('10' ~= 10) -- 不等关系,注意运算符是“~=”,不是“! =”
在执行大于或小于比较操作时Lua会检查变量的类型,如果类型不同就会出错,例如:
print(1 > "0") -- 报错,无法执行
但“==”和“~=”的行为则不同,如果类型不同会直接返回false。
实际开发中比较常见的情况是比较字符串形式的数字,为了避免发生意外,必须用函数tonumber()/tostring()显式转换数字或字符串后再做比较运算,例如:
print(1 > tonumber('0')) -- 大于比较,使用tonumber()后正常
print('10' == 10) -- 比较的类型不同,结果为false
print(tonumber('10') == 10) -- 等于关系,结果为true
3.6.3 逻辑运算
Lua的逻辑运算符有and、or和not三个,但运算规则有些特殊:
■ nil和false认为是假,其他都是真,包括数字0;
■ x and y,如果x是真,返回y,否则返回x;
■ x or y,与and操作正好相反,如果x是真,返回x,否则返回y;
■ not x,只返回true/false,对x取反。
对于C程序员来说第一条规则需要特别注意,因为在C语言里0是假,和false等价,但在Lua语言里0是真,nil和false等价,在书写条件判断代码时必须小心。
下面的代码示范了Lua里的逻辑运算:
print(0 and 'abc') --0是真,所以返回字符串’abc' print(x or 100) -- x是全局变量,值是nil,返回100 print(not x) -- x是全局变量,值是nil,返回true
利用Lua逻辑运算的特性可以实现非常灵活的赋值功能:
local x = count or 100 -- 为x赋初值,count不存在则默认值是100 local y = a and b or c -- 相当于a? b:c,由a的真假决定赋值b或c
3.6.4 字符串运算
Lua对字符串连接操作提供了一个特别的运算符“..”:
print('hello'..' '..'world') -- 连接多个字符串
连接运算还可以自动把数字转换为字符串,无须显式调用tostring()函数:
print("room number is " .. 313) -- 可以直接连接数字,无须转换
虽然Lua可以高效地处理字符串,但字符串连接操作应当尽量少用,因为每一次字符串连接就会创建一个新的字符串对象,如果多次操作超长字符串(例如几十MB的大块数据)就可能会导致LuaVM内存耗尽,发生错误。
计算字符串的长度可以用另一个特别的运算符“#”:
print(#'openresty') -- 计算字符串长度,输出9
字符串的关系运算基于字符序(例如最常用的ASCII码表)逐个检查,但相等比较是直接计算内部保存的散列值,速度很快(见3.4节):
print("a" < "b") -- 结果为true,字符序检查 print("zero" > "0") -- 结果为true,字符序检查 print("abc" == "abc") -- 结果为true,比较的是内部散列值
3.6.5 注意事项
在运算时我们需要注意操作数是nil的情形,很多时候对nil运算都会导致错误,例如:
x = nil -- x的值是nil print(1 + x) -- 出错,无法执行加法运算 print("msg is "..x) -- 出错,无法执行连接运算
如果一个变量可能是nil,最好使用or运算给它一个默认值:
print(1 + (x or 2)) -- 正常,x不存在则使用2执行加法运算 print("msg is ".. (x or "-")) -- 正常,x不存在则使用"-"执行连接运算