為啥要用位運算代替取模呢

2021-09-01 13:48:04 字數 1504 閱讀 3837

在hash中查詢key的時候,經常會發現用&取代%,先看兩段**吧,

jdk6中的hashmap中的indexfor方法:

/**

* returns index for hash code h.

*/static int indexfor(int h, int length)

redis2.4中的**段:

n.size = realsize;

n.sizemask = realsize-1;

//此處略去***行

while(de)

大家可以看到a%b取模的形式都被替換成了a&(b-1) ,當hashtable的長度是2的冪的情況下(疏忽,一開始沒寫),

這兩者是等價的,

那為什麼要用後者呢?

另一方面,為什麼hashtable的長度最好要是2的n次方呢,這個不在本次討論範圍之列,原因簡單說一下就是1、分布更均勻 2、碰撞機率更小  詳情自己思考,jdk中的hashmap就會在初始化時,保證這一點:

public hashmap(int initialcapacity, float loadfactor)
redis中也有類似的保證:

/* our hash table capability is a power of two */

static unsigned long _dictnextpower(unsigned long size)

}

int main(int argc, char* argv)

看反彙編的結果:

13:       c = a & (b-1);

00401044 mov eax,dword ptr [ebp-8]

00401047 sub eax,1

0040104a mov ecx,dword ptr [ebp-4]

0040104d and ecx,eax

0040104f mov dword ptr [ebp-0ch],ecx

14: d = a % b;

00401052 mov eax,dword ptr [ebp-4]

00401055 cdq

00401056 idiv eax,dword ptr [ebp-8]

00401059 mov dword ptr [ebp-10h],edx

可以看到,&操作用了:3mov+1and+1sub  %操作用了:2mov+1cdp+1idiv

我們可以查閱coding_asm_-_intel_instruction_set_codes_and_cycles資料,發現前者只需5個cpu週期,而後者至少需要26個cpu週期(注意,是最少!!!) 效率顯而易見。所以以後自己在寫的時候,也可以使用前者的寫法。

取模運算 和按位與

最近在研究 redis 原始碼,發現一些平時不怎麼用的編碼習慣,感覺挺有趣,記錄下 function isodd1 num function isodd2 num 以上兩個方法都是用來判斷乙個數是否為奇數,但是用到的操作符不同,有什麼區別 取模操作符是基於 十進位制 人類思維 的一種取模方式,如 1...

位運算代替常規運算

首先我們先看看1位數加法,在不考慮進製得情況下,如下 1 1 0 1 0 1 0 0 0 0 1 1顯然,這個運算可以通過異或來得到 a b 當然,這是不進製情況.實際運算我們當然要進製了,那麼,考慮一下什麼情況下會進製呢?如下,在二進位制得情況下,只有1和1相加才會進製 1 1 1 0 1 0 1...

大數取模運算

問題分析 1 大數儲存 由於x的位數最大為400位,我們不能用現有的int,long,long long,double等資料型別進行儲存。一般儲存大數的方法是用乙個字串來表示。2 取模運算 模擬手算豎式的方法。用x從高到低的每一位加上前一位餘數 10來對bi進行 最後得到的結果就是x bi的結果。利...