钳位到系列中的下一个最小值
Posted
技术标签:
【中文标题】钳位到系列中的下一个最小值【英文标题】:Clamping to next lowest value in a series 【发布时间】:2018-02-21 03:50:50 【问题描述】:我正在尝试将一个数字限制为一系列数字的较低值。例如,如果我有一个系列(抱歉记号不好)
[pq]
其中p
是任意整数,q
是任意正数。
说如果q is 50
我的系列将是...-150, -100, -50, 0, 50, 100, 150...
现在我想要一个函数f(y)
,它将任何数字夹在系列中的下一个最低数字。
例如,如果我有号码 37
,我期待的是 f(37) = 0
,我期待的是 f(-37) = -50
。
我尝试了许多涉及模数和整数除法的算法,但我似乎无法弄清楚。例如,我尝试过的最新版本是
(37 / q) * q
适用于正数,但不适用于 -50 到 0 之间的任何数字。
我也尝试过((37 - q) / q) * q
,但这不适用于完全属于该系列的负面案例。
编辑
假设我没有整个系列,而只有系列的乘数 p
。
【问题讨论】:
你不能用if
处理负数和正数之间的差异吗?
@MarkRansom `if(x
我不知道整数除法,但让我们看看是否有人比我更聪明。
@Archmede:但什么是“纯数学”,什么不是?您需要的表达式是f(y) = [y / q] * q
,其中[]
代表“向负无穷舍入”。这种四舍五入是否符合“纯数学”的条件?
【参考方案1】:
您只需使用整数欧几里得除法将y
除以q
,然后再将结果乘以q
。
f(y) = (y / q) * q
其中/
表示欧几里得除法。
在不立即支持欧几里得除法的编程语言中,您必须手动实现它或调整该语言支持的任何除法的结果。
例如,在 C 和 C++ 中,对于正除数 q
的欧几里得除法可以通过原生的“Fortran 风格”除法实现为
(y >= 0 ? y : y - q + 1) / q
所以在 C 或 C++ 中,整个表达式看起来像
f(y) = (y >= 0 ? y : y - q + 1) / q * q
37
你得到
f(37) = 37 / 50 * 50 = 0
-37
你得到
f(-37) = (-37 - 50 + 1) / 50 * 50 = -86 / 50 * 50 = -50
【讨论】:
【参考方案2】:如果您想要一种纯粹的数学方式,而不考虑计算效率,您可以通过添加一个大于或等于 |p|
并且是q
的倍数,然后通过减法将其移回。 p^2*q
满足这一点。
这给出:
((p + p^2*q) / q) * q - p^2*q
【讨论】:
【参考方案3】:确定模数结果为正数后,您可以减去该模数结果。在某些语言中,它总是是肯定的,但如果不是:
mod = p % q
positive_mod = (mod + q) % q
answer = p - positive_mod
C++ 中的结果:https://ideone.com/kIuit8
Python 中的结果:https://ideone.com/w6wUgZ
【讨论】:
以上是关于钳位到系列中的下一个最小值的主要内容,如果未能解决你的问题,请参考以下文章