久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3704|回復: 0
打印 上一主題 下一主題
收起左側

De Bruijn序列與計算二進制數計算末尾0的個數

[復制鏈接]
跳轉到指定樓層
樓主
ID:77367 發表于 2015-4-18 21:11 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  下面這個位運算小技巧可以迅速給出一個數的二進制表達中末尾有多少個 0 。比如, 123 456 的二進制表達是 1 11100010 01000000 ,因此這個程序給出的結果就是 6 。
unsigned int v;  // find the number of trailing zeros in 32-bit v
int r;           // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];

    熟悉位運算的朋友們可以認出, v & -v 的作用就是取出右起連續的 0 以及首次出現的 1 。當 v = 123 456 時, v & -v 就等于 64 ,即二進制的 1000000 。怪就怪在,這個 0x077CB531 是怎么回事?數組 MultiplyDeBruijnBitPosition 又是什么玩意兒呢?

    這還得從 0x077CB531 本身的一個性質開始說起。把這個常數寫成 32 位二進制,可以得到
00000111011111001011010100110001
    這個 01 串有一個無比牛 B 的地方:如果把它看作是循環的,它正好包含了全部 32 種可能的 5 位 01 串,既無重復,又無遺漏!其實,這樣的 01 串并不稀奇,因為構造這樣的 01 串完全等價于尋找一個有向圖中的 Euler 回路。如下圖,構造一個包含 16 個頂點的圖,頂點分別命名為 0000, 0001, 0010, …, 1111 。如果某個點的后 3 位,正好等于另一個點的前 3 位,就畫一條從前者出發指向后者的箭頭。也就是說,只要兩個頂點上的數滿足 abcd 和 bcde 的關系( a 、 b 、 c 、 d 、 e 可能代表相同的數字),就從 abcd 出發,連一條到 bcde 的路,這條路就記作 abcde 。注意,有些點之間是可以相互到達的(比如 1010 和 0101 ),有些點甚至有一條到達自己的路(比如 0000 )。
  
    構造一個字符串使其包含所有可能的 5 位 01 子串,其實就相當于沿著箭頭在上圖中游走的過程。不妨假設字符串以 0000 開頭。如果下一個數字是 1 ,那么 00001 這個子串就被包含了,同時最新的 4 位數就變成了 0001 ;但若下一個數字還是 0 ,那么 00000 就被包含了進來,最新的 4 個數仍然是 0000 。從圖上看,這無非是一個從 0000 點出發走了哪條路的問題:你是選擇了沿 00001 這條路走到了 0001 這個點,還是沿著 00000 這條路走回了 0000 這個點。同理,每添加一個數字,就相當于沿著某條路走到了一個新的點,路上所寫的 5 位數就是剛被考慮到的 5 位數。我們的目的便是既無重復又無遺漏地遍歷所有的路。顯然圖中的每個頂點入度和出度都是 2 ,因此這個圖一定存在 Euler 回路,我們便能輕易構造出一個滿足要求的 01 串了。這樣的 01 串就叫做 De Bruijn 序列。
    De Bruijn 序列在這里究竟有什么用呢?它的用途其實很簡單,就是為 32 種不同的情況提供了一個唯一索引。比方說, 1000000 后面有 6 個 0 ,將 1000000 乘以 0x077CB531 ,就得到
   00000111011111001011010100110001
-> 11011111001011010100110001000000

    相當于把 De Bruijn 序列左移了 6 位。再把這個數右移 27 位,就相當于提取出了這個數的頭 5 位:
   11011111001011010100110001000000
->                            11011

    由于 De Bruijn 序列的性質,因此當輸入數字的末尾 0 個數不同時,最后得到的這個 5 位數也不同。而數組 MultiplyDeBruijnBitPosition 則相當于一個字典的功能。 11011 轉回十進制是 27 ,于是我們查一查 MultiplyDeBruijnBitPosition[27] ,程序即返回 6 。
    注意到當輸入數字的末尾 0 個數超過 27 個時,程序也是正確的,因為左移時低位正好是用 0 填充的。
    這段神一般的代碼取自Bit Twiddling Hacks  http://graphics.stanford.edu/~seander/bithacks.html ,歡迎大家前去圍觀


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产成人啪免费观看软件 | 中文字幕精品一区 | 精品久久久久久亚洲精品 | 一区二区三区不卡视频 | 成人深夜福利 | 日日夜夜天天 | 国产一区二区三区精品久久久 | 日韩精品一区二区三区在线观看 | 中文字幕一区二区三区四区五区 | 欧美伊人久久久久久久久影院 | 超碰成人在线观看 | 天天夜夜人人 | 国产成都精品91一区二区三 | 欧美日韩国产一区二区三区 | 91在线精品视频 | 操久久 | 欧美一二区 | 依人成人 | 国产精品免费一区二区三区四区 | 91九色porny首页最多播放 | 国产精品久久久久久久久久久久久久 | 狠狠久久综合 | 日本精品在线观看 | 亚洲高清视频一区二区 | 亚洲二区在线 | 日韩在线一区二区三区 | 精品久久久久久久久久久院品网 | 91社区在线观看播放 | 亚洲国产视频一区二区 | 伊人网综合在线 | 天天成人综合网 | 精品国产乱码久久久久久丨区2区 | 国产精品久久国产精品 | 九九久久国产 | 亚洲精品天堂 | 国产高清在线精品一区二区三区 | 亚欧精品一区 | 国产精品一区二区在线 | 久久久精品国产 | 成人免费一区二区三区视频网站 | 一区二区在线看 |