Lua
语言在运行时提供了数值与字符串之间的的自动转换( conversion
)。针对字符串的所有算数操作会尝试将字符串转换为数值。 Lua
语言不仅仅在算数操作时进行这种强制类型转换( coercion
),还会在任何需要数值的情况下进行,例如函数 math.sin
的参数。
相反,当 Lua
语言发现在需要字符串的地方出现了数值时,它就会把数值转换为字符串:
print(10 .. 20) --> 1020
当在数值后紧接着使用字符串连接时,必须使用空格将他们分开,否则 Lua
语言会把第一个点当成小数点。
很多人认为自动强制类型转换算不上是 Lua
语言中的一项好设计。作为原则之一,建议最好不要完全寄希望于自动强制类型转换。虽然在某些场景下这种机制很便利,但同时也给语言和使用这种机制的程序带来了复杂性。
作为这种二类状态的表现之一, Lua5.3
没有实现强制类型转换与整型的集成,而是采用了另一种更简单和快速的实现方式:算数运算的规则就是只有在两个操作数都是整型值时结果才是整型。因此,由于字符串不是整型值,所以任何有字符串参与的算术运算都会被当做浮点运算处理:
> "10" + 1 --> 11.0
如果需要显示地将一个字符串转换成数值,那么可以使用函数 tonumber
。当这个字符串的内容不能表示为有效数字时干函数返回 nil
;否则,该函数就按照 Lua
语法扫描器的规则返回对应的整型值或浮点型值:
> tonumber(" -3 ") --> -3 > tonumber(" 10e4 ") --> 100000.0 > tonumber("10e") --> nil (not a valid number) > tonumber("0x1.3p-4") --> 0.07421875
默认情况下,函数 tonumber
使用的是十进制,但是也可以指明使用二进制到三十六进制之间的任意进制:
> tonumber("100101", 2) --> 37 > tonumber("fff", 16) --> 4095 > tonumber("-ZZ", 36) --> -1295 > tonumber("987", 8) --> nil
在最后一行中,对于指定的进制而言,传入的字符串是一个无效值,因此函数 tonumber
返回 nil
。
调用函数 tostring
可以将数值转换成字符串:
> print(tostring(10) == "10") --> true
上述的这种转换总是有效,但我们需要记住,使用这种转换时并不能控制输出字符串的格式(例如,结果中十进制数字的个数)。
与算数操作不同,比较操作符不会对操作数进行强制类型转换。请注意, "0"
和 0
是不同的。此外, 2<15
明显为真,但 "2"<"15"
却为假(字母顺序)。为了避免出现不一致的结果,当比较操作符中混用了字符串和数值时, Lua
语言会抛出异常。