计算两个区间的模数

时间:2015-06-25 17:59:21

标签: math intervals modulo integer-arithmetic

我想了解模数运算符在应用于两个区间时的工作原理。在代码中添加,减去和乘以两个区间是微不足道的,但是如何对模数进行处理?

如果有人能告诉我公式,示例代码或解释其工作原理的链接,我会很高兴。

背景信息:您有两个整数x_lo < x < x_hiy_lo < y < y_himod(x, y)的下限和上限是什么?

编辑:我不确定是否有可能以有效的方式提出最小边界(不计算所有x或所有y的mod)。如果是这样,那么我会接受一个准确但非最佳的答案。显然,[-inf,+ inf]是正确答案然后:)但我想要一个更大的限制。

2 个答案:

答案 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

...