【发布时间】:2013-02-06 11:25:49
【问题描述】:
通常在我的内部循环中,我需要以“环绕”方式对数组进行索引,因此(例如)如果数组大小为 100 并且我的代码要求元素 -2,则应为其指定元素 98 . 在 Python 等许多高级语言中,可以简单地使用my_array[index % array_size] 来完成此操作,但由于某种原因,C 的整数算术(通常)向零舍入而不是始终向下舍入,因此它的模运算符在给定时返回负结果否定的第一个参数。
我通常知道index 不会小于-array_size,在这些情况下我只做my_array[(index + array_size) % array_size]。但是,有时这无法保证,对于这些情况,我想知道实现始终为正的模函数的最快方法。有几种“聪明”的方法可以在没有分支的情况下做到这一点,例如
inline int positive_modulo(int i, int n) {
return (n + (i % n)) % n;
}
或
inline int positive_modulo(int i, int n) {
return (i % n) + (n * (i < 0));
}
当然,我可以分析这些以找出我的系统上最快的,但我不禁担心我可能错过了更好的一个,或者我的机器上的快速可能在不同的机器上很慢.
那么有没有一种标准的方法可以做到这一点,或者我错过了一些可能是最快的方法?
另外,我知道这可能是一厢情愿,但如果有一种方法可以自动矢量化,那就太棒了。
【问题讨论】:
-
你是否一直在修改相同的数字?
-
然后,您需要对模数进行硬编码,或者将其作为编译时常量放入。这样一来,您将获得比您可以使用该标志玩的任何技巧更好的性能。
-
嗯,修改 2 的幂是微不足道的;你只要
& (n-1)不管标志。 -
我很惊讶没有人指出这一点,但在 C % 中,它不是模数,它返回余数。如果您查看文档,即使 fmod 也会返回余数:cplusplus.com/reference/cmath/fmod 所以我认为调用这个正模数很奇怪,因为您正在寻找的行为是模数应该是:en.wikipedia.org/wiki/Modular_arithmetic
-
使用
(i % n) + (n * (i < 0)),我看到的结果是n而不是0负精确倍数,例如 (-3, 3) -> 3。
标签: c++ c performance