2的幂取模优化

2的幂取模优化

若被除数是正数,只需取低k位的值即可。

eg. 若k取3,则除数为8,被除数为9,则模数为9的低3位,001(2)

可以这样做的原因是第k+1位的值等于2k,也就是说大于等于k+1位的值都大于\(2^k\),他们的取值不影响余数

余数的取值范围为 \([0,2^k-1]\)

若被除数是负数,取低k位的值,还要将k位前的高位补1。

eg. 若k取3,则除数为8,被除数为-9,则模数为-9的低3位,111(2),将高位补1为\(FFFFFFFF = -1\)

由于余数的取值范围为\([-2^k,-1],当余数为2^k时,其实真正的余数应当为0\)

eg. 若k取3,则除数为8,被除数为-8,则模数为-8的低3位,000(2),将高位补1为\(FFFFFFF8 = -8\)

那么如何将-2^k,变为0呢,编译器用了一个非常巧妙的办法,就是先减1,再在高位补1,再加1。

eg. 若k取3,则除数为8,被除数为-8,则模数为-8的低3位,000(2),先减1,得111将高位补1为\(FFFFFFFF\),再加1,得0

其他的余数取值,由于减1加1没有影响高位,所以加减相互抵消,不会影响最终的取值

看看实际的汇编代码

2的幂取模优化

//当eax为-8时,

and eax,80000007 //eax=80000000

//由于eax<0,

执行dec eax //eax = 7FFFFFFF

or eax,FFFFFFF8 //eax = FFFFFFFF

inc eax //eax = 00000000

上一篇:植物大战僵尸:手工计算偏移地址


下一篇:系统调用篇——总结与提升