【问题标题】:Modulo of negative numbers [duplicate]负数的模[重复]
【发布时间】:2010-08-05 17:00:49
【问题描述】:

可能重复:
Mod of negative number is melting my brain!

我想知道是否有更好的算法来解决我正在尝试做的事情:

wrapIndex(-6, 3) = 0 wrapIndex(-5, 3) = 1 wrapIndex(-4, 3) = 2 wrapIndex(-3, 3) = 0 wrapIndex(-2, 3) = 1 wrapIndex(-1, 3) = 2 wrapIndex(0, 3) = 0 wrapIndex(1, 3) = 1 wrapIndex(2, 3) = 2 wrapIndex(3, 3) = 0 wrapIndex(4, 3) = 1 wrapIndex(5, 3) = 2

我想出了

函数 wrapIndex(i, i_max) { 如果(我 > -1) 返回 i%i_max; 变量 x = i_max + i%i_max; 如果(x == i_max) 返回0; 返回 x; }

有更好的方法吗?

【问题讨论】:

  • [负数的Mod的副本正在融化我的大脑! ](stackoverflow.com/questions/1082917/…) 以及该网站上的至少十几个问题。 :-)
  • 好吧,我搜索了负数的模,但没有真正找到任何东西...抱歉又重复了。
  • int mod(int k, int n) { return ((k %= n) < 0) ? k+n : k; }
  • 如果n 是正数,那么在Python 中(k % n) 总是正数。

标签: algorithm math modulo


【解决方案1】:

此解决方案是无分支的,但会执行两次%

function wrapIndex(i, i_max) {
   return ((i % i_max) + i_max) % i_max;
}

应该说% 的 C#/Java 行为是假设的,即结果与 红利 具有相同的符号。某些语言将余数计算定义为取 除数 的符号(例如,Clojure 中的 mod)。有些语言有两种变体(mod/rem 在 Common Lisp、Haskell 等中对)。 Algol-68 有%x,它总是返回一个非负数。 C++ 将其留给实现,直到 C++11,now the sign of the remainder is (almost) fully specified according to the dividend sign

另见

【讨论】:

  • +1 因为它确实有效。 ;-)
  • 带有分支的版本为 i_max 的负倍数返回 i_max
  • @Maciej:你是对的;把它完全拿出来(因为无论如何我都不喜欢它;只是想“完整”)。
【解决方案2】:

具有两个 % 操作的解决方案有效,但在大多数硬件上的大多数语言中,这有点快(但也有例外):

int wrapIndex(int i, int i_max) {
    i = i%i_max;
    return i<0 ? i+i_max : i;
}

【讨论】:

  • 等等,分支速度超过 2 倍?难以置信。
【解决方案3】:

更好是一个品味问题,但是怎么样

var x = (i_max + i % i_max) % i_max;

【讨论】:

  • 我真的很不舒服,因为我不知道 Java 的确切操作优先规则,或者这个问题所要求的任何语言,但我相信你知道你在做什么(感谢指正,我看到包括我在内的至少 3 人已经在这里犯了这个错误)
  • @polygenelubricants: % 在几乎所有现代语言中都优先于 +
【解决方案4】:

你可以这样做:

function wrapIndex(i, i_max) {
    if (i < 0) i = (i % i_max) + i_max;
    return i % i_max;
}

【讨论】:

  • 以前的版本是正确的 :) (i % i_max) + i_max 可能等于 i_max 如果 (i % i_max) == 0
  • @Maciej Hehl:该死,你是对的。
【解决方案5】:

许多用户给出了很好的答案,只是要小心负数,因为不同的语言可能表现不同。 例如,这个 C sn-p 写“-1”

int main ()
{
    printf("%d\n", (-4) % 3);
}

在python中我们有不同的输出值

Python 2.6.4 (r264:75706, Dec  7 2009, 18:43:55) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> (-4) % 3
2

编辑:实际上我认为您不会有负索引!不过很高兴知道这一点。

【讨论】:

    猜你喜欢
    • 2018-06-18
    • 2014-03-26
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    相关资源
    最近更新 更多