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