青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉,開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

位運算之美——用+,-和位運算實現整數除法和取模(一)

??? 今天看了一位師兄去年的筆經總結,其中有一題是“不許用%和/來實現求任意數除以3的余數”,我想考官的目的應該是想考察學生對位運算的熟悉程度吧,于是我把題目擴展成“只能用+,-和位運算實現整數除法(/)和取模(%)”,注意:這里不能使用其它的庫例程來輔助計算,如log,log10等。在思考這道題目的過程中,我又涉及到了許多二進制相關的題目,如:
??? 判斷給定的整數是不是2的整數次冪
??? 判斷給定的整數是不是4的整數次冪
??? 求給定整數的二進制表示中1的個數
??? 求給定整數的二進制表示中0的個數
??? 求給定整數的二進制表示中最高位1的位置
??? 求大于等于給定整數的最小的2的整數次冪
??? 求給定整數的二進制表示的有效位數
??? ...
??? 這些題目都是經典老題,頻繁出現于各類筆試面試題中,除了能考察位運算外,還能考察應聘者能否給出創新的算法來更好地解決問題。可以說這些題目都不難,如果使用32位的int來表示整數的話,蠻力法都可以比較好地完成任務,但是如果想盡可能地提高效率,那就需要動一番腦經了。下面給出我對這些問題的整理和C++實現,并在此基礎上給出原題(只能用+,-和位運算實現整數除法(/)和取模(%),下文都稱為原題)的實現。
??? 當然,從某種意義上講,特別是從充分利用底層硬件的計算能力(利用特殊的cpu指令)來看,這些解法肯定不是最優的,希望大俠們多多指點。
??? 還要說明的是,下面各題的順序是按照我在思考原題時的思維過程來安排的,在給出原題的實現時會詳細說明。
??? 判斷給定的整數是不是2的整數次冪
??? 這應該是最簡單的,利用最高位是1,其后所有位為0的特性,常數時間解決問題:
1?//判斷n是否是2的正整數冪
2?inline?bool?is_2exp(unsigned int?n)
3?{
4?????return?!(n&(n-1));
5?}

????求給定整數的二進制表示中1的個數
????考慮到n-1會把n的二進制表示中最低位的1置0并把其后的所有0置1,同時不改變此位置前的所有位,那么n&(n-1)即可消除這個最低位的1。這樣便有了比順序枚舉所有位更快的算法:循環消除最低位的1,循環次數即所求1的個數。此算法的時間復雜度為O(n的二進制表示中的1的個數),最壞情況下的復雜度O(n的二進制表示的總位數)。
?1//計算n的二進制表示中1的個數
?2inline?int?count1(unsigned int?n)
?3{
?4????int?r?=?0;
?5????while(n)
?6????{
?7????????n?&=?n-1;
?8????????r++;
?9????}

10????return?r;
11}
??? 既然有了求給定整數的二進制表示中1的個數的辦法,那么想要求給定整數的二進制表示中0的個數就很簡單了。事實上,在二進制中,完全可以把0和1看作是對稱的兩個對象,取反操作(~)可以任意的切換這兩個對象,只要先對n進行一次取反,然后再用上述算法即能得到二進制表示中0的個數。首先看下面的代碼:
?1//計算n的二進制表示中0的個數
?2inline?int?count0_wrong(unsigned int?n)
?3{
?4????int?r?=?0;
?5????n?&=?~n;
?6????while(n)
?7????{
?8????????n?&=?n-1;
?9????????r++;
10????}

11????return?r;
12}
??? 不知大家有沒有看出問題來?是的~操作符會把所有高位的都取反,而不是只把有效位取反,所以我們需要一個能保持高位不變的位取反操作,下面是我的實現,時間復雜度和求二進制表示中1的個數的算法相同,都與二進制表示中1的個數有關:
?1//保持高位取反
?2inline?unsigned int?negate_bits(unsigned int?n)
?3{
?4????if(n==0)?return?1;
?5????unsigned int?r=0,?m=~n;
?6????while(n)
?7????{
?8????????r?|=?(n^(n-1))&m;
?9????????n?&=?n-1;
10????}

11
12????return?r;
13}
??? 有了這個特殊的取反操作,求給定整數的二進制表示中0的個數的辦法就簡單了:
?1//計算n的二進制表示中0的個數
?2inline?int?count0(?unsigned?int?n)
?3{
?4????int?r?=?0;
?5????n?=?negate_bits(n);
?6????while(n)
?7????{
?8????????n?&=?n-1;
?9????????r++;
10????}

11????return?r;
12}
??? 看到這里,聰明的讀者肯定看出問題來了,其實我干了一件很蠢的事情。看看上述算法的時間復雜度,negate_bits花了O(n的二進制表示中1的個數),while循環計算取反后的n的二進制表示中1的個數,事實上就是O(n的二進制表示中0的個數),兩部分加起來其實就是二進制表示總的有效位數,換句話說,這個算法是線性的,而事實上,我們完全可以先線性地求出這個總的有效位數,然后減去1的位數,即得到0的位數,根本不用費那么大勁去整個保持高位的取反操作,兩者的時間復雜度在漸進意義上也是相同的。所以,我犯傻了,但是這里又引出另一個問題:

????求給定整數的二進制表示的有效位數
???
上面提到了線性地求這個位數(下文記為m),即“循環右移1位,記錄右移次數”,時間復雜度O(m)。但是我想,一看到這個題目,所有人的第一反應應該是floor(log2(n))+1吧,但是請注意,本文在一開始就規定了“不能使用庫例程”,那么在這個限制下該怎么做呢?有沒有比線性時間更好的算法呢?其實到目前為止我也沒有什么特別好的算法,希望誰有什么精妙的算法能指點一下,不要打我。。。
?1//求給定整數的二進制表示的位數,線性算法
?2int?count_bit_1(unsigned int?n)
?3{
?4????int?r?=?0;
?5????while(n)
?6????{
?7????????n>>=1;
?8????????r++;
?9????}

10????return?r;
11}

:???求大于等于給定整數的最小的2的整數次冪
????首先是最簡單的思路:求出n的二進制表示的總位數m,于是1<<m即為所求值,當然這里要排除n自身就是2的整數次冪的情況,復雜度O(m),實現如下:
?1//求大于等于n的最小的2的正整數冪,方法1
?2//時間復雜度O(n的二進制位長度)
?3unsigned int?high_2exp_1(unsigned int?n)
?4{
?5????if(n<=1)?return?1;
?6????if(is_2exp(n))?return?n;
?7
?8????unsigned int?r?=?1;
?9????while(n)
10????{
11????????n?>>=?1;
12????????r?<<=?1;
13????}

14
15????return?r;
16}
??? 事實上這就涉及到上面求二進制表示位數的問題,所以目前為止在此基礎上的算法都是線性時間的。???
??? 那有沒有不用計算位數m,從而效率更好的算法呢,能不能像在計算二進制表示中1的個數時那樣根據1的個數來設計算法呢?回到那一題中,“n-1會把n的二進制表示中最低位的1置0并把其后的所有0置1”,那么n|=n-1就把n的二進制表示中最低位1后的所有0置1,再加上1,那么就把最低位1左移了一位。于是,便有了更好的算法:循環左移最低位的1,直到n是2的整數次冪。該算法跟二進制表示中的1個數和位置有關,最壞時間復雜度還是O(二進制表示位數),但是比起上一個實現,這個算法在多數情況下都比上一個算法快。實現如下:
?1//求大于等于n的最小的2的正整數冪,方法2
?2//計算時間與n的二進制表示中1的個數和位置有關,比方法1效率高
?3//最壞情況下的時間復雜度與方法1相同
?4unsigned int?high_2exp_2(unsigned int?n)
?5{
?6????if(n<=1)?return?1;
?7
?8????while(!is_2exp(n))
?9????{
10????????n?|=?n-1;
11????????n++;
12????}

13
14????return?n;
15}
????
??? 最后來一個簡單的擴充題目:
??? 判斷給定的整數是不是4的整數次冪
????觀察4的整數次冪的特征,容易發現除了滿足n&(n-1)==0外,唯一的1位后的0的個數是偶數,這從4x=22k也能簡單地得到。這就很直觀地衍生出一個簡單的算法:
?1//判斷n是否是4的整數次冪
?2bool?is_4exp(unsigned?int?n)
?3{
?4????if(!is_2exp(n))?return?false;
?5
?6????int?bit_len?=?count_bit_1(n)-1;//線性時間求二進制位數
?7????if((bit_len&0x1)!=1)
?8????????return?true;
?9????else
10????????return?false;
11}
????算法很直觀,但是比起is_2exp的常數時間is_4exp的線性時間總讓我覺得不能接受,不過無奈還是沒有想出好辦法來,哎。。。求大牛指點啊

??? 說明:寫這篇文章,已經三次丟失全文了,把我快搞瘋了,firefox下好像有點問題,先把文章發上來,過會兒換到IE下繼續。。。
??? 再說明:換了IE后就沒再出問題了,不過寫著寫著發現寫了好久,先歇會兒,得看書補習功課了
??? 最后的說明:下次會基于上面的內容,給本文最初提出的問題(只能用+,-和位運算實現整數除法(/)和取模(%))的實現

Feedback

# re: 位運算之美——用+,-和位運算實現整數除法和取模(一)   回復  更多評論   

2010-10-25 10:20 by yu
無意中逛到這里,驚喜之。

# re: 位運算之美——用+,-和位運算實現整數除法和取模(一)   回復  更多評論   

2010-11-18 16:06 by zl
最后的說明:下次會基于上面的內容,給本文最初提出的問題(只能用+,-和位運算實現整數除法(/)和取模(%))的實現
在那里?

# re: 位運算之美——用+,-和位運算實現整數除法和取模(一)   回復  更多評論   

2011-09-25 12:03 by skyworm
n &= ~n; // 寫錯啦,這個操作之后,n就永遠等于0了。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            9色国产精品| 国产在线日韩| 免费观看日韩| 欧美在线观看视频在线| 欧美与欧洲交xxxx免费观看| 欧美亚洲免费在线| 久久久国产亚洲精品| 久久久久久久综合| 欧美成人一区二区三区| 亚洲精品国产精品乱码不99| 久久综合色8888| 亚洲黄色尤物视频| 日韩网站在线| 欧美一级大片在线免费观看| 久久精品亚洲热| 欧美乱在线观看| 国产欧美一区在线| 亚洲理伦在线| 欧美在线电影| 亚洲国产精品t66y| 亚洲欧美国产另类| 欧美xxx在线观看| 国产精品久久网站| 亚洲黄色一区| 久久成年人视频| 亚洲国产清纯| 欧美中文字幕视频在线观看| 欧美另类在线观看| 精品9999| 新狼窝色av性久久久久久| 欧美黑人一区二区三区| 亚洲综合导航| 欧美激情一区二区三区在线视频观看 | 国产亚洲精品自拍| 亚洲日韩视频| 久久精品亚洲| 亚洲午夜精品久久久久久浪潮| 久久久福利视频| 国产精品国产三级国产专播精品人| 一区二区视频免费完整版观看| 国产精品99久久久久久人| 久久全球大尺度高清视频| 亚洲美洲欧洲综合国产一区| 久久久久久久久伊人| 国产欧美亚洲视频| 亚洲影院免费观看| 亚洲欧洲综合| 你懂的成人av| 亚洲激情自拍| 欧美国产激情二区三区| 久久精品国产亚洲5555| 国产三区二区一区久久 | 久久亚洲精品中文字幕冲田杏梨| 亚洲综合色在线| 日韩亚洲欧美高清| 欧美不卡在线| 久久爱www久久做| 国产欧美不卡| 欧美在线关看| 欧美综合国产精品久久丁香| 国产亚洲精品久久久久动| 欧美一区成人| 欧美一区二区三区视频免费播放| 国产精品日韩久久久久| 午夜在线成人av| 亚洲欧美日韩在线观看a三区 | 一区二区三区无毛| 老司机午夜精品视频在线观看| 欧美在线视频免费| 狠狠色狠狠色综合| 猛男gaygay欧美视频| 美女网站在线免费欧美精品| 亚洲激精日韩激精欧美精品| 亚洲电影天堂av| 欧美日韩xxxxx| 亚洲欧美日韩国产综合| 亚洲欧美日韩国产综合| 狠狠色综合播放一区二区| 免费亚洲一区二区| 欧美日韩国产在线播放网站| 午夜在线a亚洲v天堂网2018| 久久成人精品无人区| 亚洲三级毛片| 亚洲一区欧美激情| 1024日韩| 这里是久久伊人| 今天的高清视频免费播放成人 | 亚洲一级在线| 午夜激情综合网| 狠狠狠色丁香婷婷综合激情| 亚洲国产免费看| 国产欧美va欧美va香蕉在| 欧美大胆成人| 国产精品色网| 亚洲高清三级视频| 国产精品一区视频| 亚洲国产精品久久久久婷婷884| 国产精品盗摄久久久| 欧美bbbxxxxx| 国产伦精品一区二区三区| 亚洲大黄网站| 国产视频欧美视频| 日韩一级片网址| 激情国产一区| 亚洲一二区在线| 亚洲国产mv| 午夜精品视频一区| 99pao成人国产永久免费视频| 午夜精品免费在线| 亚洲素人一区二区| 翔田千里一区二区| 欧美成黄导航| 久久爱91午夜羞羞| 欧美黄色片免费观看| 久久久一二三| 国产精品一二一区| 亚洲看片一区| 亚洲精品国产视频| 久久久免费av| 久久久中精品2020中文| 国产精品视频一| 99热在这里有精品免费| 亚洲精品在线观看免费| 久久中文字幕导航| 久久久久综合网| 国产亚洲毛片| 欧美亚洲视频在线看网址| 亚洲综合成人婷婷小说| 欧美日韩美女一区二区| 亚洲片在线观看| 亚洲精品乱码久久久久久蜜桃91| 久久女同精品一区二区| 久久影院午夜论| 在线观看的日韩av| 久久综合中文| 亚洲大片在线观看| 亚洲成色最大综合在线| 久久日韩粉嫩一区二区三区| 久久婷婷蜜乳一本欲蜜臀| 国内久久视频| 久久免费黄色| 欧美国产专区| 99视频精品免费观看| 欧美日韩1区2区3区| 一本色道久久综合一区| 午夜一区二区三区在线观看| 国产日韩欧美三级| 久久久噜噜噜久久中文字幕色伊伊| 美女主播精品视频一二三四| 亚洲激情偷拍| 欧美三级免费| 亚洲欧美一区二区在线观看| 久久久综合免费视频| 亚洲国产精选| 欧美久色视频| 亚洲神马久久| 久久嫩草精品久久久精品| 亚洲激情成人网| 欧美午夜免费电影| 欧美一级一区| 亚洲国产mv| 午夜在线观看欧美| 好看的日韩视频| 欧美日韩在线视频首页| 香蕉久久精品日日躁夜夜躁| 久久一二三四| 一本色道久久88精品综合| 国产精品一区二区三区久久| 久久精品国产亚洲高清剧情介绍| 亚洲大片av| 欧美一级视频免费在线观看| 在线成人亚洲| 国产精品久久久久天堂| 久久在线91| 亚洲私人影院在线观看| 欧美成人免费大片| 欧美一区二区三区视频免费播放| 亚洲国产91色在线| 国产丝袜一区二区三区| 欧美激情一区二区三区在线视频| 亚洲永久免费精品| 亚洲黄色视屏| 国产一区二区精品在线观看| 亚洲永久免费精品| 欧美激情亚洲一区| 午夜精品剧场| 99pao成人国产永久免费视频| 国产亚洲第一区| 欧美三级日本三级少妇99| 麻豆国产va免费精品高清在线| 亚洲性图久久| 日韩视频一区二区在线观看 | 亚洲黄网站在线观看| 欧美在线一二三区| 一区二区欧美在线观看| 亚洲国产精品热久久| 国产亚洲成av人片在线观看桃| 欧美日韩亚洲一区二区三区在线观看| 久久久久久亚洲精品不卡4k岛国| 亚洲一区制服诱惑|