5.3 之前:只有 float

Lua 5.1 / 5.2 / LuaJIT 的 number 是 IEEE 754 double——能表示整数 ±2^53 内无损,但没有真整数类型

-- 5.1 / LuaJIT
print(1)        -- "1" (其实是 1.0)
print(1/0)      -- inf
print(0/0)      -- nan
print(1 / 2)    -- 0.5

位运算?没原生支持。要用 BitOp 库(LuaJIT 自带)或 bit32 库(5.2 临时方案)。

5.3+:真整数

Lua 5.3 引入 64 位整数子类型:

print(math.type(1))     -- "integer"
print(math.type(1.0))   -- "float"
print(math.type(1+1))   -- "integer"
print(math.type(1+0.5)) -- "float"

整数和浮点会自动转换:

print(1 + 1.0)          -- 2.0(浮点参与 → 结果浮点)
print(10 / 3)           -- 3.3333... (/ 总返回浮点)
print(10 // 3)          -- 3   (// 整数除法)
print(10 % 3)           -- 1

范围

print(math.maxinteger)   -- 9223372036854775807 (2^63 - 1)
print(math.mininteger)   -- -9223372036854775808

64 位有符号。超出范围会回绕(不抛错)。

位运算操作符(5.3+)

含义
& AND
| OR
~ XOR(二元) / NOT(一元)
<< 左移
>> 右移(逻辑)
print(0xF0 & 0x0F)       -- 0
print(0xF0 | 0x0F)       -- 255 (0xFF)
print(0xFF ~ 0x0F)       -- 240 (0xF0)
print(~0)                -- -1(all bits set)
print(1 << 4)            -- 16
print(256 >> 4)          -- 16

注意 ~ 同时是 XOR(二元)和 NOT(一元)——和 C 不同(C 是 ^ XOR、~ NOT)。

LuaJIT 怎么办

LuaJIT 长期停在 Lua 5.1 语法。位运算用内置的 bit 库:

local bit = require("bit")   -- LuaJIT 自带

bit.band(0xF0, 0x0F)         -- AND
bit.bor(0xF0, 0x0F)          -- OR
bit.bxor(0xFF, 0x0F)         -- XOR
bit.bnot(0)                  -- NOT
bit.lshift(1, 4)             -- 左移
bit.rshift(256, 4)           -- 右移(逻辑)
bit.arshift(-1, 4)           -- 算术右移

32 位操作(不是 64)。需要 64 位用 ffi.uint64_t + ffi.arith 操作。

tonumber 处理整数

tonumber("42")          -- 42 (integer)
tonumber("42.0")        -- 42.0 (float)
tonumber("ff", 16)      -- 255 (integer)
tonumber("0x1p4")       -- 16.0 (5.3+: 十六进制浮点)

强制转换

math.tointeger(3.0)     -- 3
math.tointeger(3.5)     -- nil(无法无损转)
math.tointeger("4")     -- 4

3 | 0                   -- 把 float 强制成 integer?不行,| 要求两边都是 integer 表示的值
math.floor(3.5)         -- 3(但返回的是 integer,5.3+)

跨版本兼容写法

-- 移植性:检测整数支持
local has_integer = math.type ~= nil

local function band(a, b)
    if has_integer then return a & b end
    return bit.band(a, b)            -- LuaJIT
end

或写两套代码——很多 Lua 项目维护两个分支:一套 5.1/LuaJIT,一套 5.3+。

浮点的坑

print(0.1 + 0.2 == 0.3)    -- false(经典浮点问题)
print(0.1 + 0.2)            -- 0.30000000000000004

比较浮点用容差:

local function near(a, b) return math.abs(a - b) < 1e-9 end

→ 下一篇 性能与常见坑