钳位到系列中的下一个最低值

Clamping to next lowest value in a series

我正在尝试将一个数字限定为一系列数字中的较低值。例如,如果我有一个系列(抱歉符号错误)

[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

您可以在确定模数结果为正后减去模数结果。在某些语言中,它 总是 是正数,但如果不是:

mod = p % q
positive_mod = (mod + q) % q
answer = p - positive_mod

C++ 结果:https://ideone.com/kIuit8

结果Python:https://ideone.com/w6wUgZ

如果你想要纯数学的方式,不考虑计算效率,你可以将输入p移到正整数范围内,加上一个大于或等于[=的正整数11=] 是 q 的倍数,然后再减去。 p^2*q 满足这个。

这给出: ((p + p^2*q) / q) * q - p^2*q

您只需使用整数欧氏除法将 y 除以 q,然后再将结果乘以 q

f(y) = (y / q) * q

其中 / 表示欧氏除法。

在不立即支持欧氏除法的编程语言中,您将不得不手动实现它或调整该语言支持的任何除法的结果。

例如,在 C 和 C++ 中,正除数的欧几里德除法 q 可以通过本机 "Fortran-style" 除法实现为

 (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