0Pricing
Lua Academy · 课时

类型强制转换和显式转换

学习字符串与数字之间的自动强制转换,以及显式调用 tonumber/tostring。

类型强制转换和显式转换 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。

什么是类型强制转换?

类型强制转换是指:当上下文需要时,自动将一个值从一种类型转换为另一种类型。Lua 会在两个特定方向上执行强制转换:算术上下文中的字符串转数字,以及拼接上下文中的数字转字符串。

与 JavaScript 不同,Lua 的强制转换范围有限且行为可预测。它不会自动将布尔值转换为数字,也不会自动将表转换为字符串。

-- String to number (arithmetic context)
print("10" + 5)     -- 15  (coerced)
print("3.14" * 2)   -- 6.28

-- Number to string (concatenation context)
print(10 .. "px")   -- 10px
print(3.14 .. "!")  -- 3.14!

-- No boolean coercion
-- print(true + 1)  -- ERROR!

字符串转数字的强制转换规则

当字符串出现在算术表达式中时,Lua 会尝试将其转换为数字。如果字符串不表示有效数字,就会引发运行时错误。有效的数字字符串包括整数("42")、浮点数("3.14")、十六进制数("0xff")和科学计数法表示的数字("1e3")。

带有前导或尾随空白的字符串也会被接受——Lua 会在强制转换过程中去除这些空白。

print("42" + 0)      -- 42    (integer)
print("3.14" + 0)    -- 3.14  (float)
print("0xff" + 0)    -- 255   (hex)
print("  10  " + 0)  -- 10    (whitespace ok)
print("1e3" + 0)     -- 1000.0

-- This will error:
-- print("hello" + 0)  -- attempt to perform arithmetic on a string value

数字转字符串的强制转换

使用 .. 拼接数字时,Lua 会自动将数字转换为字符串。整数会变成十进制表示;浮点数可能会出现小数位。若要精确控制格式,请始终使用 tostring() 或 string.format(),不要依赖隐式强制转换。

print(10 .. "!")       -- 10!
print(3.14 .. "!")     -- 3.14!
print(1/3 .. "!")      -- 0.33333333333333!

-- Explicit is better for precision
print(string.format("%.2f", 1/3))  -- 0.33
print(tostring(10))                -- 10
print(tostring(10.0))              -- 10.0

tonumber():显式转换

tonumber(v) 会将一个值显式转换为数字。转换成功时,它返回转换后的数字;转换失败时返回 nil,而且绝不会引发错误。解析整数时可以指定可选的进制(2–36),从而支持二进制、八进制和十六进制转换。

处理用户输入时,请始终检查 tonumber() 的返回值是否为 nil。

print(tonumber("42"))      -- 42
print(tonumber("3.14"))    -- 3.14
print(tonumber("0xFF"))    -- 255
print(tonumber("hello"))   -- nil (no error!)
print(tonumber(true))      -- nil

-- Base conversion
print(tonumber("ff", 16))  -- 255
print(tonumber("11", 2))   -- 3   (binary)
print(tonumber("77", 8))   -- 63  (octal)

tostring():显式转换

tostring(v) 会将任意值转换为字符串。对于数字,它会生成十进制或科学计数法表示的字符串。对于布尔值,它会生成 "true" 或 "false"。对于 nil,它返回 "nil"。对于表和函数,除非定义了 __tostring 元方法,否则它会返回类似 "table: 0x..." 的地址。

print(tostring(42))         -- 42
print(tostring(3.14))       -- 3.14
print(tostring(true))       -- true
print(tostring(false))      -- false
print(tostring(nil))        -- nil
print(tostring({}))         -- table: 0x...

-- Useful for safe concatenation
local val = nil
local msg = "Value: " .. tostring(val)
print(msg)   -- Value: nil

math.tointeger()

math.tointeger(x)(Lua 5.3+)仅在浮点数具有精确整数表示时,才会将其转换为整数。如果转换会损失精度,则返回 nil。这比 math.floor() 更安全,后者总会成功,但可能会在不提示的情况下截断数值。

当您需要严格验证整数时可以使用此函数,例如与要求精确整数的 API 对接时。

print(math.tointeger(5.0))   -- 5   (exact)
print(math.tointeger(5.5))   -- nil (not exact)
print(math.tointeger(2^53))  -- 9007199254740992

-- Contrast with math.floor
print(math.floor(5.9))       -- 5   (truncates)
print(math.floor(5.0))       -- 5

-- Check before use
local n = math.tointeger(val) or error("need integer")

比较中的强制转换

Lua 在相等比较时不会进行类型强制转换。1 == "1" 始终为 false,因为两个操作数的类型不同。不过,关系运算符(<、> 等)会触发字符串与数字之间的强制转换——但前提是两个操作数的类型相同。在排序比较中混合不同类型会引发错误。

print(1 == "1")    -- false (no coercion)
print(1 == 1.0)    -- true  (int/float equal)

-- Ordering: same type only
print("abc" < "abd")  -- true (string compare)
print(1 < 2)          -- true (number compare)

-- This ERRORS: mixing string and number
-- print(1 < "2")  -- attempt to compare number with string

实践:解析用户输入

Lua 程序中非常常见的一种模式是读取用户输入中的字符串(例如通过 io.read()),然后将其转换为数字。请始终使用 tonumber() 并检查是否为 nil,以便优雅地处理无效输入,而不是让程序崩溃。

-- Safe input parsing pattern
local function parseNumber(input)
  local n = tonumber(input)
  if n == nil then
    return nil, "Invalid number: " .. tostring(input)
  end
  return n, nil
end

local val, err = parseNumber("42")
print(val, err)   -- 42  nil

local val2, err2 = parseNumber("abc")
print(val2, err2) -- nil  Invalid number: abc

整数与浮点数的精度陷阱

浮点数的精度有限。混合整数和浮点数的运算可能会由于 IEEE 754 表示方式而产生意外结果。双精度数能够精确表示的最大整数是 2^53 = 9,007,199,254,740,992。超过此范围的整数存储为浮点数时会损失精度。

在 Lua 5.3+ 中,原生 64 位整数支持最大到 2^63-1 的精确值,范围大得多。需要保证精确性时,请始终使用整数算术运算。

-- Float precision limit
print(2^53)            -- 9.007...e+15
print(2^53 + 1 == 2^53) -- true (precision lost!)

-- Integer stays exact
local big = math.maxinteger
print(big)             -- 9223372036854775807
print(math.type(big))  -- integer

-- Mixing promotes to float
print(math.type(1 + 1.0))  -- float

字符串格式转换

当您需要控制精度、填充和表示法时,string.format() 是数字转字符串最强大的工具。它遵循 C 语言的 printf 格式说明符。请在显示、文件输出以及默认的 tostring() 表示不够用的任何场景中使用它。

print(string.format("%d", 255))      -- 255
print(string.format("%x", 255))      -- ff
print(string.format("%05d", 42))     -- 00042
print(string.format("%.2f", 3.14159)) -- 3.14
print(string.format("%e", 12345.0))  -- 1.234500e+04
print(string.format("%s=%d", "x", 10)) -- x=10

快速检查

在 Lua 中,tonumber("hello") 返回什么?

回顾:类型强制转换与转换

您已经学到:

  • Lua 会在算术运算中自动将字符串强制转换为数字,并在拼接中自动将数字强制转换为字符串
  • tonumber() 失败时返回 nil——请始终检查!
  • tostring() 可以安全地将任意值转换为字符串
  • 相等比较(==)绝不会进行强制转换——不同类型的值永远不相等
  • 使用 string.format() 精确格式化数字
  • 浮点数的精度上限为 2^53;需要表示较大的精确值时,请使用原生整数

下一节:使用 if/elseif/else 和循环控制流程。

常见问题解答

「类型强制转换和显式转换」课时是免费的吗?

是的 — 「类型强制转换和显式转换」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「类型强制转换和显式转换」这节课中我会学到什么?

学习字符串与数字之间的自动强制转换,以及显式调用 tonumber/tostring。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「类型强制转换和显式转换」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Lua 数据类型概览
  2. 在 Lua 中声明变量
  3. 算术运算符和关系运算符
  4. 类型强制转换和显式转换
← 返回 Lua Academy