luaguides

tonumber

tonumber() converts a value to a number. If the value cannot be converted, it returns nil.

Signature

tonumber(e, base)

Parameters:

  • e — the value to convert (string or number)
  • base — optional number base (2 to 36, default 10)

Returns: number, or nil if conversion fails.

Converting Numbers

Pass a number and it comes back unchanged:

tonumber(42)        -- 42
tonumber(3.14)      -- 3.14
tonumber(-17)       -- -17

This is mostly useful when you need a guaranteed number type.

Converting Strings

The most common use is parsing strings:

tonumber("42")        -- 42
tonumber("3.14")       -- 3.14
tonumber("  100  ")    -- 100 (whitespace is ignored)

If the string is not a valid number, you get nil:

tonumber("hello")    -- nil
tonumber("42abc")    -- nil
tonumber("")         -- nil

Using Base (Radix) Parsing

The second argument specifies the number base. Bases 2 through 36 are supported.

Binary (base 2)

tonumber("1010", 2)   -- 10
tonumber("1111", 2)   -- 15

Hexadecimal (base 16)

tonumber("FF", 16)     -- 255
tonumber("0xFF", 16)   -- 255 (0x prefix also recognized)
tonumber("0xabcd", 16) -- 43981

Hex digits are case-insensitive: tonumber("AbCd", 16) returns 43981.

Octal (base 8)

tonumber("77", 8)    -- 63
tonumber("040", 8)   -- 32

Watch out: Lua does not treat a leading zero as octal by default. tonumber("040") returns 40, not 32. You must pass base 8 explicitly.

Other Bases

Base can be any integer from 2 to 36:

tonumber("Z", 36)     -- 35
tonumber("100", 3)     -- 9

Digits beyond 9 use letters a-z (case-insensitive) for values 10-35.

Error Handling

tonumber never throws an error — it returns nil for invalid input:

result = tonumber("not a number")
if result == nil then
    print("invalid input")
end

You can combine with assert if you want an error on bad input:

value = assert(tonumber("42"), "must be a number")     -- 42
value = assert(tonumber("oops"), "must be a number")   -- error: must be a number

Practical Examples

Parsing User Input

local input = io.read("*line")
local n = tonumber(input)
if n then
    print("Twice that is:", n * 2)
else
    print("'" .. input .. "' is not a number")
end

Reading Hex Colours

local hex = "3A7D44"
local r = tonumber(string.sub(hex, 1, 2), 16)
local g = tonumber(string.sub(hex, 3, 4), 16)
local b = tonumber(string.sub(hex, 5, 6), 16)
print(r, g, b)  -- 58 125 68

Configuration Files

config = {
    width  = tonumber("800"),
    height = tonumber("600"),
    scale  = tonumber("1.5"),
}

if config.width and config.height then
    print(config.width * config.height)
end

See Also