Lua 取整,取余

本文介绍了Python中math.modf和math.mod函数的用法。math.modf用于分离数值的整数部分与小数部分,而math.mod则实现取模运算。通过具体示例展示了如何使用这两个函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[新的博客地址](shankusu.me)

一下内容转载或引用或参考

http://blog.youkuaiyun.com/goodai007/article/details/17142915

使用math.modf(x/y)此函数,第一参数返回整数部分,第二个参数返回小数部分

t1,t2 = math.modf(30/10);

math.mod(x,y)函数,返回模

取模运算

math.mod(19, 10)

9

<think>我们正在讨论Lua中的取整操作,具体表达式为:a=a-a%1这个表达式的作用是将浮点数a向下取整(向负无穷方向取整)吗?实际上,它实现的是向零取整(truncate)。让我们分析一下:对于非负数:例如:a=3.7a%1的结果是0.7(因为模运算会得到小数部分)那么a-a%1=3.7-0.7=3.0->向下取整(也是向零取整)对于负数:例如:a=-3.7在Lua中,负数模运算的结果是非负的(因为模运算的结果的符号由第二个参数决定,这里第二个参数是1(正数),所以结果是非负的)。所以,-3.7%1等于多少?我们需要计算:-3.7除以1的余数余数的定义是:a%b=a-floor(a/b)*b计算:a/b=-3.7/1=-3.7,floor(-3.7)=-4(因为floor是向下取整,即向负无穷方向取整)所以:-3.7%1=-3.7-(-4)*1=-3.7+4=0.3那么:a-a%1=-3.7-0.3=-4.0->这个结果并不是我们期望的向零取整(向零取整应该是-3),而是向下取整(向负无穷方向取整)了?但是,请注意:在Lua5.3之前,模运算对于负数的处理与整数除法(floor除法)有关。而Lua5.3引入了整数除法浮点数除法的区分,但是模运算仍然遵循:a%b=a-math.floor(a/b)*b所以,我们重新计算一下:对于负数:a=-3.7a%1=-3.7%1=(-3.7)-math.floor(-3.7/1)*1=(-3.7)-math.floor(-3.7)*1=(-3.7)-(-4)*1=-3.7+4=0.3那么a-a%1=-3.7-0.3=-4.0因此,表达式a=a-a%1对于负数得到的是-4.0,而向零取整应该是-3(即去掉小数部分,直接取整数部分)。所以这个表达式对负数并不是向零取整。实际上,这个表达式对正数可以实现向零取整(即去掉小数部分),但对负数则是向下取整(向负无穷方向取整)。因此,整体效果是向零取整吗?不是,因为正数部分向零,负数部分向负无穷,不一致。然而,我们注意到:在Lua中,对于负数的模运算,其行为可能导致这个表达式并不像预期那样工作。但事实上,在Lua中,如果我们使用这个表达式,它确实可以实现向零取整吗?我们再看一个例子:对于负数:a=-1.5计算:a%1=-1.5%1=(-1.5)-math.floor(-1.5)=(-1.5)-(-2)=0.5那么a-a%1=-1.5-0.5=-2.0而向零取整应该是-1(因为-1.5的整数部分向零方向是-1)。所以,这个表达式得到的是-2,并不是-1。因此,这个表达式实际上实现的是向下取整(floor)?因为正数部分3.7变成3(向下取整),负数部分-3.7变成-4(向下取整),-1.5变成-2(向下取整)?是的,因为对于正数,向下取整向零取整是一样的;对于负数,向下取整就是往更小的整数方向。所以,表达式a=a-a%1实际上是实现了向下取整(floor)的功能。但是,我们通常使用math.floor(x)来向下取整。那么,这个表达式math.floor(x)等价吗?对于正数:等价。对于负数:也等价?因为math.floor(-3.7)等于-4,math.floor(-1.5)等于-2。所以,这个表达式的作用就是向下取整(floor)。然而,我们再看一个整数的情况:a=55%1=0,所以5-0=5->正确。所以,结论:表达式a=a-a%1的效果等同于math.floor(a),即向下取整。但是,为什么会有这样的写法?可能是因为在某些环境中(比如嵌入式设备)为了减少函数调用(避免使用math库)而采用的一种技巧。另外,需要注意的是:这个表达式对于整数也是成立的,因为整数的小数部分为0。用法:我们可以直接这样写来对数字进行向下取整。但有一个问题:当a为负数时,模运算的结果是正的小数部分,然后减去这个正的小数部分,相当于把负数的小数部分(绝对值)加到了负数的整数部分上(因为减去一个正数相当于加上一个负数),从而使得结果更小(向下取整)。因此,我们可以这样使用:a=3.7a=a-a%1-->a变为3.0a=-3.7a=a-a%1-->a变为-4.0但是,这个表达式得到的结果是浮点数形式(即使结果是整数,也是3.0这样的形式)。如果我们想要整数,可以使用math.floor,它返回的是整数吗?注意,在Lua中,math.floor返回的是浮点数(因为Lua中所有数字都是浮点数,除非使用Lua5.3+的整数)。在Lua5.3及以上版本,数字有整数浮点数之分。但是,math.floor返回的是整数类型(如果输入是整数或浮点数,返回的是整数类型的数,但实际上是浮点数表示整数,或者整数类型)。但是,在Lua5.3之前,所有数字都是浮点数,所以返回的也是浮点数。所以,表达式a=a-a%1得到的结果math.floor(a)一样,都是浮点数(或整数)表示。因此,我们可以这样总结:这个表达式实现了向下取整(floor),与math.floor函数功能相同。但是,为什么有人用这个表达式而不用math.floor?可能的原因:1.避免使用math库(在没有导入math库的情况下)2.在某些环境中,可能这个表达式比函数调用更快(但通常math.floor是内置的,应该很快)另外,我们还要注意,这个表达式对于NaNinf的情况可能不会正常工作,而math.floor可能会处理(返回NaN或inf)。所以,在大多数情况下,推荐使用math.floor,因为它的意图更明确。但是,如果确实需要避免使用math库,那么这个表达式是一个可行的替代方案。最后,我们还要注意,这个表达式只适用于实数,不适用于复数等其他类型。因此,在Lua中,使用a=a-a%1进行取整的原理是:通过模运算得到小数部分(对于负数,模运算得到的是正的小数部分),然后用原数减去这个小数部分,从而得到向下取整的结果。用法示例:x=7.89x=x-x%1-->x=7.0y=-7.89y=y-y%1-->y=-8.0(注意:在Lua中,-7.89向下取整是-8.0)但是,如果我们想要向零取整(即正数向下取整,负数向上取整),应该怎么做?向零取整:正数去掉小数部分,负数也去掉小数部分(即绝对值更小的整数)。例如:3.7->3,-3.7->-3我们可以使用:a>=0andmath.floor(a)ormath.ceil(a)或者:a-a%1只能得到向下取整,所以我们可以这样写:如果a是正数,用a-a%1;如果a是负数,用a-a%1+1?不对,因为负数时a%1是正的小数部分,比如-3.7%1=0.3,那么-3.7-0.3=-4,然后加1得到-3。但是,这样写:a-a%1+(a<0and1or0)?不对,因为当a为负数时,我们加了1,那么-4+1=-3,正确。但是,当a是整数时,比如-4,-4%1=0,然后-4-0+1=-3,但我们期望的是-4(整数不需要变)?不对,因为-4的向零取整是-4?不对,向零取整就是它本身(整数部分),所以-4就是-4,我们不需要改变。所以,这个表达式对整数也适用吗?因为整数的小数部分为0,所以a%1=0,那么负数整数:a<0时,表达式变成a-0+1,即a+1,这就不对了。因此,我们需要判断:如果a是负数,并且a%1不等于0,那么加1;否则不加。这样写比较复杂。更简单的方法是:使用math.modf函数,它返回整数部分小数部分,其中整数部分是向零取整的。或者,我们可以用:a>=0and(a-a%1)or(a-a%1+(a%1>0and1or0))这样写很复杂。实际上,向零取整可以通过以下方式:a=(a>=0)andmath.floor(a)ormath.ceil(a)或者,使用模运算的另一种写法:a-a%1得到的是向下取整,那么对于负数,向下取整比向零取整小1(当小数部分不为0时),所以:ifa<0anda%1~=0thena=a-a%1+1elsea=a-a%1end但是,这样写比较繁琐。所以,通常建议使用math.tointeger(如果只是取整,且希望得到整数)或者math.modf(返回两个值:整数部分小数部分,整数部分向零取整)或者直接使用条件表达式。总结:表达式a=a-a%1是向下取整(floor)操作,与math.floor(a)等效。参考引用:在Lua的官方文档中,模运算定义为:a%b==a-math.floor(a/b)*b[^1]因此,我们可以得出结论:该表达式利用了模运算的定义,通过减去小数部分(即模1的结果)来得到整数部分(向下取整)。相关问题:1.这个表达式对于非常大的数字(比如1e20)是否有效?2.Lua中还有哪些取整的方法?3.如何实现向零取整(truncate)?4.这个表达式在Lua5.1、5.2、5.3等不同版本中行为是否一致?</think>在 Lua 中,表达式 `a = a - a % 1` 是一种**向下取整(floor)** 的数学技巧,其原理用法如下: ### 原理分析 1. **模运算 `%` 的特性**: - `a % 1` 计算 `a` 除以 1 的余数,等价于 `a` 的小数部分。 - 对于正数: - 例如 `a = 3.7` 时:`3.7 % 1 = 0.7` - 此时 `a - a % 1 = 3.7 - 0.7 = 3.0`(向下取整) - 对于负数: - 例如 `a = -2.3` 时:`-2.3 % 1 = 0.7`(Lua模结果总是非负) - 此时 `a - a % 1 = -2.3 - 0.7 = -3.0`(向负无穷方向取整) 2. **数学本质**: - 表达式等价于 $\text{a} - (\text{a} \mod 1)$。 - 通过减去小数部分,将浮点数截断为**不大于原数的最大整数**,即数学上的 $\lfloor a \rfloor$。 3. **边界情况**: - 若 `a` 是整数(如 `5.0`):`a % 1 = 0`,结果不变。 - 若 `a` 为负小数(如 `-1.5`):`-1.5 % 1 = 0.5`,结果为 `-1.5 - 0.5 = -2.0`。 ### 用法示例 ```lua -- 正数取整 local x = 7.89 x = x - x % 1 --> 结果为 7.0 -- 负数取整 local y = -4.2 y = y - y % 1 --> 结果为 -5.0 -- 整数不变 local z = 10.0 z = z - z % 1 --> 结果为 10.0 ``` ### 注意事项 1. **与 `math.floor` 的等价性**: - 此表达式完全等价于 `math.floor(a)`,但无需引入 `math` 库。 - 例如:`-3.7 - (-3.7 % 1)` `math.floor(-3.7)` 结果均为 `-4.0`。 2. **结果类型**: - 输出始终为**浮点数**(如 `3.0` 而非整数 `3`),因 Lua 默认所有数值为浮点类型。 3. **适用场景**: - 轻量化脚本中避免依赖 `math` 库。 - 需明确向下取整逻辑时(如网格坐标计算)。 ### 与其他取整方法对比 | **方法** | **方向** | **示例(输入 `-2.3`)** | **示例(输入 `3.7`)** | |---------------------|----------------|--------------------------|------------------------| | `a - a % 1` | 向下取整 | `-3.0` | `3.0` | | `math.floor(a)` | 向下取整 | `-3.0` | `3.0` | | `math.ceil(a)` | 向上取整 | `-2.0` | `4.0` | | `a // 1` (Lua 5.3+) | 向零取整 | `-2.0` | `3.0` | > **提示**:若需**向零取整**(正数向下、负数向上),可用 `math.tointeger(a)` 或 `a // 1`(Lua 5.3+)[^1]。 --- ### 相关问题 1. Lua 中如何实现**四舍五入**取整? 2. 为什么 `-2.3 % 1` 在 Lua 中结果是 `0.7` 而非 `-0.3`? 3. 如何在不使用 `math` 库的情况下实现**向上取整**? 4. Lua 5.3 新增的整数除法 `//` 有哪些特性? [^1]: Lua 官方文档:模运算定义 `a % b = a - math.floor(a/b)*b`,确保结果符号与除数一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值