【问题标题】:Calculating the modulo of two intervals计算两个区间的模
【发布时间】:2015-06-25 17:59:20
【问题描述】:

我想了解模运算符在应用于两个区间时的工作原理。两个区间的加减乘乘在代码中实现起来很简单,但是模数怎么做呢?

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

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

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

【问题讨论】:

  • one区间的模数是如何定义的?
  • 不是。我之后的操作是 两个 间隔的模数,就像你可以划分两个间隔一样。
  • 如果 y 是固定的,可以通过查看 mod(x_lo, y) 和 mod(x_hi, y) 来计算范围。但是随着 y 的变化,mod 值中没有简单的模式。我认为除了计算每个 y 的 mod(x_lo, y) 和 mod(x_hi, y) 并取它们绑定的区间的并集之外,这里没有什么可做的。

标签: math intervals modulo integer-arithmetic


【解决方案1】:

事实证明,这是一个有趣的问题。我所做的假设是,对于 整数 间隔,模是相对于 截断除法 定义的(向 0 舍入)。

因此,mod(-a,m) == -mod(a,m) 代表所有 a、m。此外,sign(mod(a,m)) == sign(a).

定义,在我们开始之前

a 到 b 的闭区间: [a,b]
空区间: [] := [+Inf,-Inf]
否定: @987654325 @
联合: [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

玩得开心! :)

【讨论】:

    【解决方案2】:

    让我们看看 mod(x, y) = mod. 通常 0

    但我们可以在下面看到一些具体的案例:

    - 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
    

    ....

    【讨论】:

    • 您正在考虑未为负数定义的类似余数运算。但在mod([2,2], [-3,-3]) = [2,2] 中,y_lo &lt; mod &lt; y_hi 不正确。
    • y € [2,4], x € [2,4] -> 取 x = 3, y = 3, 结果:0。查看上面的语句并填写值给出 1
    猜你喜欢
    • 2016-10-19
    • 1970-01-01
    • 2018-02-26
    • 2014-02-08
    • 2014-06-11
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    相关资源
    最近更新 更多