高效的Modulo 3操作
Efficient Modulo 3 operation?
可能重复:
快速模3还是除法算法?
每个人都知道模运算可能是性能上的一个巨大缺点。有人知道x%3操作的好替代方案吗?我知道x%2存在一个缓冲区,但我真的需要一个用于模3的缓冲区,因为我想在for循环中的三个缓冲区之间交替。
谢谢!
好吧,不是通常的"测量它",而是一个实际的答案——因为这些东西实际上是真正有趣的数学。尽管编译器也可以而且可能做到这一点(至少在现代优化c++编译器中,javac肯定不会,我也不知道JVM是否做到了(,但最好检查一下它是否还没有为您完成这项工作。
但了解优化背后的理论仍然很有趣:我将使用汇编,因为我们需要乘法中更高的32位字。以下是沃伦关于比特游戏的书:
n是我们想要取模的输入整数:
li M, 0x55555556 ; load magical number (2^32 + 2) / 3
mulhs q, M, n ; q = higher word of M * n; i.e. q = floor(M*n / 2^32)
shri t, n, 31 ; add 1 to q if it is negative
add q, q, t
这里q包含n/3的除数,所以我们照常计算余数:r = n - q*3
数学是有趣的部分——乳胶在这里会很酷:
q=楼层((2^32+2(/3*(n/2^32((=楼层(n/3+2*n/(3*2^32(
现在,对于n=2^31-1(有符号32位整数可能的最大n(,误差项小于1/3(并且是非负的(,这使得很容易证明结果确实是正确的。对于n=-2^31,我们有上面1的修正,如果你简化它,你会发现误差项总是大于-1/3,这意味着它也适用于负数。
我把误差项边界的证明留给感兴趣的人——这并不难。
如果是在一个直循环中,则无需计算模。保持第二个int var,每3步重置一次。
int i, bn = 0;
for(i=0; i<whatever; i++) {
...
if(++bn == 3) bn = 0;
}
这不是一个过早的优化,它避免了不必要的计算。
编辑:OP中说他使用循环在缓冲区之间切换,所以我的解决方案看起来很合适。至于否决票,如果这是一个错误,那没问题。
如果在编译时已知3
,则编译器将生成尽可能高效的"技巧"。当除数未知时,直到运行时,模需要更长的时间。
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 重载操作程序时出错>>用于类中的字符串 memebr
- 对字符串进行位操作
- 我可以在 C++ 中的函数体之外进行操作吗?
- MPI突然停止了对多个核心的操作
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 对字符数组中的元素执行逐位操作
- 如何在directx/c++中进行平移/缩放操作
- 逐位操作的隐式类型转换
- 为什么一个向量上的多线程操作很慢
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 位移操作和位掩码未检测到重复字符
- 如何进行特定的位操作?
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 字符串操作 - 字符计数
- 此代码中的操作流程是什么?C/C++.
- 是``if`语句''在modulo之前和分配操作之前的冗余
- 使用Modulo操作的正确方法
- 无法在C++中为SAFECRAC SPOJ正确使用MODULO操作
- 高效的Modulo 3操作