02 - 数值类型

争取两三周入门 Lua!

在 Lua5.3 以前,所有数值都以双精度浮点格式表示。从 Lua5.3 开始,Lua 为数值格式(number)提供了两种选择:

  • 64 位整型 integer
  • 双精度浮点型 float

如果资源受限,可将 Lua 编译为精简 Lua(Small Lua)模式,该模式使用 32 位整型和单精度浮点型。

数值常量

可用科学计数法书写数值常量:

4.57e-3		--> 0.00457

具有十进制小数或者指数的数值会被当做浮点型值,否则会被当做整型值。

由于整型值和浮点型值的类型都是 数值 (number),它们是可以相互转换的:

   
type(-3) --> number type(-3.0) --> number -3 == -3.0 --> true

如果要区分数值是整型还是浮点型,可用 math.type()

math.type(3)	--> integer
math.type(3.0)	--> float

Lua 也支持以 0x 开头的十六进制常量,还支持十六进制的浮点数,这种十六进制浮点数由小数部分和以 p/P 开头的指数部分组成:

   
0xff --> 255 0x0.2 --> 0.125 0xa.bp2 --> 42.75

可用 string.format()%a 参数格式化输出十六进制小数:

string.format("%a", 419)	--> 0x1.a3p+8

虽然这种格式很难阅读,但可保留浮点数精度且比十进制转换速度更快。

运算符

算数运算

加减法:

   
13 + 15 --> 28 13.0 + 15.0 --> 28.0 13 + 15.0 --> 28.0

乘法:

-(3 * 6.0)	--> -18.0

除法:

3.0 / 2.0	--> 1.5
3 / 2		--> 1.5

如果想要整数除法,需要用 //,它会将结果向下取整:

   
3 // 2 --> 1 3.0 // 2 --> 1.0 -9 // 2 --> -5

取模:

   
-- 模运算定义: a % b == ((a // b) * b) 5 % 2 --> 1 -- 实数模运算: 获得模数后面位数的实数 x = math.pi x % 0.01 --> 0.0015926535897931 x - x % 0.01 --> 3.14

幂运算:

4^0.5	--> 2.0

关系运算

Lua 提供下列关系运算:

<	>	<=	>=	==	~=

这些关系运算的结果都是 Boolean 类型,~= 是不等号。

运算符优先级

Lua 的运算符优先级如下(从高到低):

   
^ 一元运算符(- # ~ not) * / // % + - .. (连接) << >> (按位移位) & (按位与) ~ (按位异或) | (按位或) < > <= >= ~= == and or

数学库

Lua 提供了标准数学库 math。由一组标准的数学函数组成,包括三角函数 (sin, cos, tan, asin 等),指数函数,取整函数,最大最小函数,生成伪随机数的函数等;并且有常量 pi 和 huge(最大表示数值,在大多数平台上为 inf)。

三角函数

以弧度为单位,通过函数 degrad 进行角度和弧度的转换:

math.sin(math.rad(30)) 		--> 0.5
math.deg(math.asin(0.5))	--> 30.0

随机数发生器

函数 math.random 用于生成伪随机数,有三种调用方式:

  • 不带参数调用:返回一个在 [0,1) 范围内均匀分布的伪随机实数。
  • 带整型 n 的调用:返回一个在 [1,n] 范围内的伪随机整数。
  • 带整型 l 和 u 的调用:返回在 [l,u] 范围内的伪随机整数。

函数 math.randomseed 用于设置伪随机数发生器的种子,该函数的唯一参数就是数值类型的种子。在程序启动时,随机数发生器的种子固定为 1,为了解决这个问题,通常用 math.randomseed(os.time()) 来设置种子。

取整函数

数学库提供了 3 个取整函数:

  • 向负无穷取整 floor
  • 向正无穷取整 ceil
  • 向 0 取整 modf

当取整结果能够用整型表示时,返回结果为整型,否则返回浮点型。除了返回取整后的值外,modf 还会返回小数部分作为第二个结果。

如果要让数值 x 向最近整数取整,可这样写:

   
function round(x) local f = math.floor(x) if (x == f) or (x % 2.0 == 0.5) then return f else return math.floor(x + 0.6) end end round(2.5) --> 2 round(3.5) --> 4 round(-1.5) --> -2

数值范围

数学库中的常量定义了整型值的最大值 math.maxinteger 和最小值 math.mininteger。在标准 Lua(64 位)中,最大为​。超过最大值会发生整型溢出,即发生回环。

math.maxinteger + 2	 --> -9223372036854775807

对于浮点数而言,在标准 Lua 中,64 位双精度浮点数可以表示范围从的数;精简 Lua 中,32 位单精度浮点数,可以表示范围从​的数。如果浮点数发生溢出,结果会被取近似。

math.maxinteger + 2.0 == math.maxinteger + 1.0  --> true

整型与浮点型转换

整型 -> 浮点型

可以将在范围内的整型转换为浮点型:

-3 + 0.0	--> -3.0

浮点型 -> 整型

浮点型可通过位运算方式强制转换为整型:

2^53 | 0	--> 9007199254740992

如果浮点数有小数部分或不在整型范围内,会抛出异常:

3.2 | 0 
stdin:1: number has no integer representation

除此之外,还能用 math.tointeger 将数值类型强制转换为整型,无法转换时返回 nil

math.tointeger(-258.0)		--> -258
math.tointeger(5.01)		--> nil

这个函数在需要检查一个数字能否被转换成整型值时尤为有用。例如,以下函数在可能时会将输入参数转换为整型值,否则保持原来的值不变:

   
function cond2int(x) return math.tointeger(x) or x end