Lua
语言提供了标准数学库 math
。标准数学库由一组标准的数学函数组成,包括三角函数( sin
、 cos
、 tan
、 asin
等)、指数函数、取整函数、最大和最小函数max
和 min
、用于生成伪随机数的伪随机函数( random
)以及常量 pi
和 huge
(最大可表示数值,在大多数平台上代表 inf
)。
所有的三角函数都是以弧度为单位,并通过函数 deg
和 red
进行角度和弧度转换。
随机数发生器
函数 math.random
用于生成伪随机数,共有三种调用方式。
- 当不带参数调用时,该函数将返回一个在
[0, 1)
范围内均匀分布的伪随机数。 - 当使用带有一个整型值n的参数调用时,该函数将返回一个在
[1, n]
范围内的伪随机整数。例如,可以通过调用random(6)
来模拟掷骰子的结果。 - 当使用带有两个整数值
l
和u
的参数调用时,该函数返回在[l, u]
范围内的伪随机数。
函数 randomseed
用于设置伪随机数发生器的种子,该函数的唯一参数就是数值类型的种子。在一个程序启动时,系统国定使用 1
为种子初始化伪随机数发生器。如果不设置其他的种子,那么每次程序运行时都会生成相同的伪随机数序列。从调试角度看,这是一个不错的特性,然而,对于一个游戏来说却会导致相同的场景重复不断的出现。为了解决这个问题,通常调用 math.randomseed(os.time())
来使用当前系统时间作为种子初始化随机数发生器。
取整函数
数学库提供了三个取整函数: floor
、 ceil
和 modf
。作用如下表所示:
函数 | 作用 |
floor | 向负无穷取整 |
ceil | 向正无穷取整 |
modf | 向零取整 |
当取整结果能够用整型表示时,返回结果为整型值,否则返回浮点型值(当然,表示的还是整数值)。
除了返回取整后的值以外,函数 modf
还会返回小数部分作为第二个结果。
> math.floor(3.3) --> 3 > math.floor(-3.3) --> -4 > math.ceil(3.3) --> 4 > math.ceil(-3.3) --> -3 > math.modf(3.3) --> 3 0.3 > math.modf(-3.3) --> -3 -0.3 > math.floor(2^70) --> 1.1805916207174e+21
如果参数本身就是一个整型值,那么它将被原样返回。
如果将数值 x
向最近的整数取整,可以对 x+0.5
调用 floor
函数。不过,当参数是一个很大的整数时,简单的加法可能会导致错误。例如,考虑如下代码:
x = 2 ^ 52 + 1 print(string.format("%d %d", x, math.floor(x + 0.5))) --> 4503599627370497 4503599627370498
252 + 1.5的浮点值表示是不精确的,因此内部会以我们不可控的方式取整。为了避免这个问题,我们可以单独的处理整数值:
function round(x) local f = math.floor(x) if x == f then return f else return math.floor(x + 0.5) end end
上面的函数总是会向上取整半个整数。
如果想进行无偏取整,即向距离最近的偶数取半个整数,上述公式在 x+0.5
是奇数的情况下会产生不正确的结果
> math.floor(3.5 + 0.5) --> 4 (ok) > math.floor(2.5 + 0.5) --> 4 (wrong)
这时,还是可以利用取整操作来解决上述公式中存在的问题:表达式 x%2.0==0.5
只会在 x+0.5
为奇数时(也就是我们的公式会出错的情况)为真。基于这些情况,定义一个无偏取整函数就简单多了,如下所示:
function round(x) local f = math.floor(x) if (x == f) or (x % 2 == 0.5) then return f else return math.floor(x + 0.5) end end print(round(2.5)) --> 2 print(round(3.5)) --> 4 print(round(-2.5)) --> -2 print(round(-1.5)) --> -2