Break stuff. Now.

Lua Numbers Can Be Double Or Something Else

More knobs to turn and rugs to pull

January 1, 2022

Woman head-desk on laptop Photo by Andrea Piacquadio from Pexels

Lua numbers are double by default, but can be configured to be something else (e.g. float, long, etc.). This is to make Lua be flexible and accommodate different constraints, such as limited number types on the embedding environment, precision requirements, bytecode size requirements, standards requirements, just to name a few.

This also means that there is a chance of mismatch. Bytecode generated by a tool whose Lua is configured for one type will not be compatible with a consuming application whose Lua is configured to expect another type. When this happens, it results in an error similar to the following:

# Interpreter expects a double, bytecode supplies a float
luac: virtual machine mismatch in your.lua: size of number is 8 but read 4

# Interpreter expects a float, bytecode supplies a double
luac: virtual machine mismatch in your.lua: size of number is 4 but read 8

To change the underlying number type, you will need to recompile either the tool that uses Lua to produce the bytecode, or the tool that uses Lua to consume the bytecode, to use the same number type as the other. These modifications are done on files depending on the version of Lua you're using, either on lua.h (5.0.x) or luaconf.h (5.1+).

For example, the following modifications switch Lua from the default double to float:

  • LUA_NUMBER from double to float
  • LUA_NUMBER_SCAN from %lf to "%f"
  • LUA_NUMBER_FMT from "%.14g" to "%.7g"
  • lua_str2number from strtod to strtof
  • l_mathop(x) to (x##f)