我想了解模数运算符在应用于两个区间时的工作原理。在代码中添加,减去和乘以两个区间是微不足道的,但是如何对模数进行处理?
如果有人能告诉我公式,示例代码或解释其工作原理的链接,我会很高兴。
背景信息:您有两个整数x_lo < x < x_hi
和y_lo < y < y_hi
。 mod(x, y)
的下限和上限是什么?
编辑:我不确定是否有可能以有效的方式提出最小边界(不计算所有x或所有y的mod)。如果是这样,那么我会接受一个准确但非最佳的答案。显然,[-inf,+ inf]是正确答案然后:)但我想要一个更大的限制。
答案 0 :(得分:1)
事实证明,这是一个有趣的问题。我所做的假设是,对于整数间隔,模数是针对截断除法定义的(朝0取整)。
因此,mod(-a,m) == -mod(a,m)
对所有a,m。此外,sign(mod(a,m)) == sign(a)
。
从a到b的间隔时间: [a,b]
空间隔:[] := [+Inf,-Inf]
否定:-[a,b] := [-b,-a]
联盟::[a,b] u [c,d] := [min(a,c),max(b,d)]
绝对值: |m| := max(m,-m)
m
从固定的m
开始比较容易。稍后我们将其概括为两个间隔的模。该定义将递归建立。以您喜欢的编程语言来实现它应该没有问题。伪代码:
def mod1([a,b], m):
// (1): empty interval
if a > b || m == 0:
return []
// (2): compute modulo with positive interval and negate
else if b < 0:
return -mod1([-b,-a], m)
// (3): split into negative and non-negative interval, compute and join
else if a < 0:
return mod1([a,-1], m) u mod1([0,b], m)
// (4): there is no k > 0 such that a < k*m <= b
else if b-a < |m| && a % m <= b % m:
return [a % m, b % m]
// (5): we can't do better than that
else
return [0,|m|-1]
到目前为止,我们不能做得更好。 (5)
中的结果间隔可能有点过高,但这是我们所能得到的最好的间隔。如果允许我们返回一组时间间隔,则可以更精确。
相同的想法适用于模数本身是间隔的情况。我们开始:
def mod2([a,b], [m,n]):
// (1): empty interval
if a > b || m > n:
return []
// (2): compute modulo with positive interval and negate
else if b < 0:
return -mod2([-b,-a], [m,n])
// (3): split into negative and non-negative interval, compute, and join
else if a < 0:
return mod2([a,-1], [m,n]) u mod2([0,b], [m,n])
// (4): use the simpler function from before
else if m == n:
return mod1([a,b], m)
// (5): use only non-negative m and n
else if n <= 0:
return mod2([a,b], [-n,-m])
// (6): similar to (5), make modulus non-negative
else if m <= 0:
return mod2([a,b], [1, max(-m,n)])
// (7): compare to (4) in mod1, check b-a < |modulus|
else if b-a >= n:
return [0,n-1]
// (8): similar to (7), split interval, compute, and join
else if b-a >= m:
return [0, b-a-1] u mod2([a,b], [b-a+1,n])
// (9): modulo has no effect
else if m > b:
return [a,b]
// (10): there is some overlapping of [a,b] and [n,m]
else if n > b:
return [0,b]
// (11): either compute all possibilities and join, or be imprecise
else:
return [0,n-1] // imprecise
玩得开心! :)
答案 1 :(得分:0)
让我们看看mod(x,y)= mod。 通常0 <= mod&lt; = y。所以它总是如此:y_lo&lt; mod&lt; y_hi
但我们可以看到下面的一些具体案例:
- if: x_hi < y_lo then div(x, y) = 0, then x_low < mod < x_hi
- if: x_low > y_hi then div(x, y) > 0, then y_low < mod < y_hi
- if: x_low < y_low < y_hi < x_hi, then y_low < mod < y_hi
- if: x_low < y_low < x_hi < y_hi, then y_low < mod < x_hi
- if: y_low < x_low < y_hi < x_hi, then y_low < mod < y_hi
...