Mic*_*ith 3 c c++ java performance modulo
可能重复:
快速模3或除法算法?
每个人都知道模运算可能是性能上的一个巨大缺点.有没有人知道x%3操作的好选择?我知道x%2存在一个,但我真的需要一个模3,因为我想在for循环中在三个缓冲区之间交替.
谢谢!
Voo*_*Voo 10
而不是通常的"衡量它"是一个真正的答案 - 因为那些东西实际上是真正有趣的数学.虽然编译器可以并且也可能这样做(至少现代优化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
Run Code Online (Sandbox Code Playgroud)
这里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;
}
Run Code Online (Sandbox Code Playgroud)
这不是一个过早的优化,它避免了不必要的计算.
编辑:在OP中声明他使用循环在缓冲区之间切换,所以我的解决方案看起来非常合适.至于downvote,如果是一个错误,没问题.
| 归档时间: |
|
| 查看次数: |
4324 次 |
| 最近记录: |