• <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>
            OnTheWay2012
            埋葬昨天的我,迎來重生的我!
            posts - 15,  comments - 89,  trackbacks - 0

            求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?
            這是一道面試題可以用以下的一些方案。
            第一種是很容易想到的采用循環(huán)的方式并且與1進(jìn)行位與運(yùn)算,具體代碼如下。

             1unsigned int GetBitNumOfOne_ByLoop1(unsigned int nValue)
             2{
             3 const unsigned int nNumOfBitInByte = 8;
             4 unsigned int nBitMask = 1;
             5 unsigned int nBitNum = 0;
             6 for(unsigned int i = 0 ; i < sizeof(nValue) * nNumOfBitInByte ; i++)
             7 {
             8  (0 < (nValue & nBitMask)) ? nBitNum++ : 0;
             9  nBitMask<<=1;
            10 }

            11 return nBitNum;
            12}

            13unsigned int GetBitNumOfOne_ByLoop2(unsigned int nValue)
            14{
            15 const unsigned int nNumOfBitInByte = 8;
            16 unsigned int nBitMask = 1;
            17 unsigned int nBitNum = 0;
            18 for(unsigned int i = 0 ; i < sizeof(nValue) * nNumOfBitInByte ; i++)
            19 {
            20  (0 < (nValue & nBitMask)) ? nBitNum++ : 0;
            21  nValue>>=1;
            22 }

            23 return nBitNum;
            24}

            這兩種做法很相像,卻別就是在是對(duì)nBitMask進(jìn)行左移還是對(duì)nValue進(jìn)行右移。
            當(dāng)然了以上的兩個(gè)方法存在一個(gè)問題:不管如何這個(gè)函數(shù)肯定要循環(huán)32次(對(duì)于32平臺(tái)來說)。
            那又沒有更好的方法?當(dāng)然有,請(qǐng)看下面:
             1unsigned int GetBitNumOfOne_ByLoop3(unsigned int nValue)
             2{
             3 unsigned int nBitNum = 0;
             4 while(0 < nValue)
             5 {
             6  nValue &=(nValue - 1);
             7  nBitNum++;
             8 }

             9 return nBitNum;
            10}

            假如使用參數(shù)12345(二進(jìn)制是11000000111001)調(diào)用該函數(shù),該函數(shù)的執(zhí)行情況如下:
            第一次進(jìn)入循環(huán)
            0 < 11000000111001
            11000000111001 &= (11000000111001 - 1) 之后 nValue 的值 是 11000000111000
            nBitNum 的值是1
            經(jīng)過本次循環(huán)之后11000000111001 變成了 11000000111000 比之前少了一個(gè)1
            第二次進(jìn)入循環(huán)
            0 < 11000000111000
            11000000111000 &= (11000000111000 - 1) 之后 nValue 的值 是 11000000110000
            nBitNum 的值是2
            經(jīng)過本次循環(huán)之后11000000111000 變成了 11000000110000 比之前少了一個(gè)1
            第三次進(jìn)入循環(huán)
            0 < 11000000110000
            11000000110000 &= (11000000110000 - 1) 之后 nValue 的值 是 11000000100000
            nBitNum 的值是3
            經(jīng)過本次循環(huán)之后11000000110000 變成了 11000000100000 比之前少了一個(gè)1
            經(jīng)過以上3次循環(huán)情況的說明,我相信你一定看出了些什么吧。nValue &=(nValue - 1),這句
            代碼實(shí)際上就是把nValue 的某位及其以后的所有位都變成0,當(dāng)nValue最后變成0的時(shí)候循環(huán)結(jié)束,
            且nBitNum 記錄的就是1的個(gè)數(shù)。
            上面的做法已經(jīng)很不錯(cuò)了,但是作為程序員的你是否會(huì)有疑問,“還有其他的方法嗎?”。
            有,當(dāng)然有!請(qǐng)看下面的代碼:
             1unsigned int GetBitNumOfOne(unsigned int nValue)
             2{
             3 nValue = ((0xaaaaaaaa & nValue)>>1+ (0x55555555 & nValue);
             4 nValue = ((0xcccccccc & nValue)>>2+ (0x33333333 & nValue);
             5 nValue = ((0xf0f0f0f0 & nValue)>>4+ (0x0f0f0f0f & nValue);
             6 nValue = ((0xff00ff00 & nValue)>>8+ (0x00ff00ff & nValue);
             7 nValue = ((0xffff0000 & nValue)>>16+ (0x0000ffff & nValue);
             8 
             9 return nValue;
            10}


            假如你是第一次看到這些代碼,你是否能看明白?呵呵,本人第一次看到這些代碼的時(shí)候看了好久才感覺
            好像有點(diǎn)明白。下面我就以一個(gè)例子來說明上面的代碼是如何做到的。
            假如參數(shù)是0xffffffff。
            第一行代碼:
            nValue = ((0xaaaaaaaa & nValue)>>1) + (0x55555555 & nValue);
            a的二進(jìn)制表示是:1010
            5的二進(jìn)制表示是:0101
            0xffffffff 與 0xaaaaaaaa 進(jìn)行與運(yùn)算之后是0x10101010101010101010101010101010
            然后再進(jìn)行左移操作后是0x01010101010101010101010101010101
            0x55555555 & nValue 進(jìn)行與運(yùn)算之后是0x01010101010101010101010101010101
            然后0x01010101010101010101010101010101 & 0x01010101010101010101010101010101
            得到0x10101010101010101010101010101010
            我們把得到的結(jié)果分成16組0x10  10  10  10  10  10  10  10  10  10  10  10  10  10  10  10
            每組的10單獨(dú)來看是不是十進(jìn)制的2
            我們0x01010101010101010101010101010101和0x01010101010101010101010101010101這兩個(gè)數(shù)也按照上面的方法分成
            16個(gè)組0x01  01  01  01  01  01  01  01  01  01  01  01  01  01  01  01
                  0x01  01  01  01  01  01  01  01  01  01  01  01  01  01  01  01
            那么這兩個(gè)數(shù)的每一個(gè)組都是01 那么兩個(gè)01 里面有幾個(gè)1,是不是2個(gè)。這是2是不是二進(jìn)制的10,然后16個(gè)10組合起來是不是
            0x10101010101010101010101010101010

            第二行代碼:
            nValue = ((0xcccccccc & nValue)>>2) + (0x33333333 & nValue);
            此時(shí)nValue是0x10101010101010101010101010101010
            c的二進(jìn)制表示是:1100
            3的二進(jìn)制表示是:0011
            0xcccccccc 與 nValue) 進(jìn)行與運(yùn)算之后是0x10001000100010001000100010001000
            然后再進(jìn)行左移操作后是0x00100010001000100010001000100010
            0x33333333 & nValue 進(jìn)行與運(yùn)算之后是0x00100010001000100010001000100010

            然后0x00100010001000100010001000100010 & 0x00100010001000100010001000100010
            得到0x01000100010001000100010001000100
            我們把得到的結(jié)果分成8組0x0100 0100 0100 0100 0100 0100 0100 0100
            每組的0100單獨(dú)來看是不是十進(jìn)制的4 總共有多少個(gè)4?是不是8個(gè),8×4=32。

            以下的代碼:
             nValue = ((0xf0f0f0f0 & nValue)>>4) + (0x0f0f0f0f & nValue);
             nValue = ((0xff00ff00 & nValue)>>8) + (0x00ff00ff & nValue);
             nValue = ((0xffff0000 & nValue)>>16) + (0x0000ffff & nValue);
            請(qǐng)自己按照上面的方法做一遍,就會(huì)發(fā)現(xiàn)規(guī)律:第一次32位數(shù)分成32組,第二次分成16組,第三次分成8,第四次分成4,第五次分成2組。
            如果還是不明白請(qǐng)多看看,然后多選擇幾個(gè)參數(shù)進(jìn)行試驗(yàn),多試幾次肯定會(huì)明白的。


            看了這么多解法是不是有中很過癮的感覺,當(dāng)我知道有這么多解法是也很過癮,也很遺憾。遺憾什么呢?遺憾當(dāng)時(shí)我碰到這道面試題的時(shí)候
            只想到了采用循環(huán)的方法,可是那個(gè)面試題上明確說明不準(zhǔn)使用循環(huán)!!當(dāng)時(shí)很郁悶!!
            鄭重聲明:上面最后兩個(gè)解法非本人原創(chuàng),本人只是總結(jié)歸納,向想出這么好方法的前輩高人致敬!

            posted on 2010-03-24 18:02 OnTheWay 閱讀(6173) 評(píng)論(15)  編輯 收藏 引用 所屬分類: 面經(jīng)

            FeedBack:
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-25 17:00 | 樂蜂專賣店
            案件的驕傲是巨大  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-25 17:01 | hoodlum1980
            一個(gè)UINT32,寫成16進(jìn)制字符串,是“00000000”,“FFFFFFFF”。
            “0”到“F”,可以做一個(gè)16個(gè)元素的數(shù)組,該數(shù)組提供每個(gè)字母中 1 的個(gè)數(shù)。

            這樣我們把這個(gè)數(shù)字格式化成16進(jìn)制的字符串,然后用查表法,累加每個(gè)字母位于數(shù)組中的1的個(gè)數(shù)即可。

            例如:“0”: 0000; 1的個(gè)數(shù) = 0, “F”:1111; 1的個(gè)數(shù)=4;

            不知可行否?  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-25 18:10 | OnTheWay
            不可行。
            你的方法的思想是有點(diǎn)類似于桶排序的思想,但是是不可行的。
            首先從時(shí)間效率和空間效率上看與上述的任何一個(gè)方案相比都沒有優(yōu)勢。
            另外在計(jì)算機(jī)里數(shù)據(jù)是按照二進(jìn)制的方式進(jìn)行存儲(chǔ)的,按照你的方案還需要把二進(jìn)制再轉(zhuǎn)換成16進(jìn)制的,如果你能進(jìn)行轉(zhuǎn)換的話,很可能說明此時(shí)你已經(jīng)知道了這些二進(jìn)制位中有多少個(gè)1了。  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-25 18:11 | OnTheWay
            @樂蜂專賣店
            別在這里做廣告了。  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-25 18:12 | hoodlum1980
            補(bǔ)全一下代碼:
            #include <stdio.h>
            #include <string.h>
            int GetBitNumOfOne_ByHoodlum(unsigned int nValue)
            {
            size_t i;
            int count = 0;
            char *CharSet = "0123456789ABCDEF";

            //每個(gè)字符中含有的1的個(gè)數(shù)
            int table[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
            char str[12];
            sprintf(str, "%X", nValue);
            size_t length = strlen(str);
            for(i=0; i < length; i++)
            {
            count += table[ strchr(CharSet, str[i]) - CharSet ];
            }
            return count;
            }  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-25 18:32 | OnTheWay
            @hoodlum1980
            呵呵,我的理解有誤,按照你的方案確實(shí)可以實(shí)現(xiàn)。
            不過時(shí)間效率和空間效率確實(shí)不是太高。
            另外如果可以使用這么多系統(tǒng)函數(shù)的話,那還是使用標(biāo)準(zhǔn)庫的bitset方便些。
            代碼如下:
            #include <iostream>
            #include <bitset>
            #include <algorithm>

            using namespace std;

            size_t GetBitNumOfOne_ByBitSet(unsigned int nValue)
            {
            const size_t sizeBitNum = 8;
            bitset<sizeof(unsigned int) * sizeBitNum> TestBitSet(nValue);
            string strContent = TestBitSet.to_string();
            return std::count(strContent.begin(), strContent.end(), '1');
            }

            void main()
            {
            //測試數(shù)據(jù)
            cout<<GetBitNumOfOne_ByBitSet(0)<<endl;
            cout<<GetBitNumOfOne_ByBitSet(1)<<endl;
            cout<<GetBitNumOfOne_ByBitSet(2)<<endl;
            cout<<GetBitNumOfOne_ByBitSet(123)<<endl;
            cout<<GetBitNumOfOne_ByBitSet(0xff)<<endl;
            }  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)[未登錄]
            2010-03-26 09:52 | hh
            先計(jì)算出結(jié)果, 找規(guī)律

            之后重寫程序, 兩字: 查表  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-03-29 12:53 | 小時(shí)候可靚了
            查表吧,反正是有限位,建一個(gè)表
            比如 0 0 ,1 1, 2 1 , 3 2...  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)[未登錄]
            2010-03-31 14:54 | tom
            試過std::bitset沒?可以用int直接構(gòu)造,再循環(huán)調(diào)用std::bitset::test()測試每一位就齊活。  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-04-04 22:29 | ARush
            #include "stdafx.h"
            #include <stdio.h>
            //得到一個(gè)unsigned int整數(shù)的二進(jìn)制表示中1的數(shù)目
            int GetNO(unsigned int number);
            int _tmain(int argc, _TCHAR* argv[])
            {
            int number;
            puts("input a int number");
            while(scanf("%d",&number)==1)
            {
            int result=0;
            result=GetNO(number);
            printf("\nthe length of %d is %d\n",number,result);
            puts("input a int number");
            }
            return 0;
            }
            int GetNO(unsigned int number)
            {
            int size=sizeof(unsigned int)*8;
            int result=0;
            for(int i=0;i<size;i++,number>>=1)
            {
            if(number==0)
            break;
            if((01&number)==01)
            result++;
            }
            return result;
            }  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-04-08 11:53 | jmchxy
            調(diào)用任何系統(tǒng)函數(shù)都會(huì)增加時(shí)間空間效率, 循環(huán)調(diào)用 bitset::test 不會(huì)比第一種方法更好。 sprintf 轉(zhuǎn)換到16進(jìn)制本身就需要進(jìn)行一次循環(huán)除法取余, std::count 同樣是循環(huán)算法. 第三種方法是常數(shù)復(fù)雜度,最快的。  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-04-29 17:05 | D
            int countbit(int n)
            {
            int c;
            for(c=0;n;n>>=1) c+=n&1;
            return c;
            }
              回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)[未登錄]
            2010-05-29 11:26 | hdqqq
            unsigned long val ;
            int count = 0;
            while(val) {
            count += (val & 1) ;
            val >>= 1;
            }  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)[未登錄]
            2010-05-29 11:30 | hdqqq
            @hdqqq
            上面已經(jīng)貼了類似的,我的作廢。  回復(fù)  更多評(píng)論
              
            # re: 一道面試題(求一個(gè)unsigned int 數(shù)的二進(jìn)制表示中有多少個(gè)1?)
            2010-11-24 23:22 | triangle
            @OnTheWay
            第一行代碼:nValue = ((0xaaaaaaaa & nValue)>>1) + (0x55555555 & nValue);
            將32位數(shù)分為16組,判斷出每兩位中有多少個(gè)1,并用兩位來表示結(jié)果。
            (0xaaaaaaaa & nValue)>>1) 計(jì)算偶數(shù)位是否為1; 如10&10>>1 = 01
            (0x55555555 & nValue) 計(jì)算基數(shù)為是否為1; 如10&01= 00
            兩數(shù)相加得出10中包含的1的個(gè)數(shù)為0x01;
            后面的代碼則是如何將16組2位數(shù)相加得出最后的結(jié)果。
            第二行代碼:((0xcccccccc & nValue)>>2) + (0x33333333 & nValue);
            將nValue的分成8組,每組中的兩兩相加;
            如(0110 & 1100)>>2 + (0110 & 0011) = 0011; 即 01 + 10 = 0011;
            同理:
            第三行代碼: 將nValue分成4組,每組中的兩兩相加,也就是每4位相加,結(jié)果保存在8位數(shù)中。
            第四行代碼: 將nValue分成2組,每組中的兩兩相加,也就是每8位相加,結(jié)果保存在16位數(shù)中。
            第五行代碼: 將nValue分成1組,每組中的兩兩相加,也就是每16位相加,結(jié)果保存在32位數(shù)中。






              回復(fù)  更多評(píng)論
              

            <2010年5月>
            2526272829301
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            友情連接

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            亚洲国产欧洲综合997久久| 国产一久久香蕉国产线看观看| 99久久精品午夜一区二区| 久久夜色精品国产亚洲| 激情久久久久久久久久| 一本久久免费视频| 久久天堂AV综合合色蜜桃网| 精品国产婷婷久久久| 久久久久久国产a免费观看不卡| 国产精品久久婷婷六月丁香| 久久久久无码精品国产不卡| 亚洲国产高清精品线久久| 久久久久久久精品成人热色戒| 狠狠色综合久久久久尤物| 久久精品日日躁夜夜躁欧美 | 色综合久久综合网观看| 精品久久人人妻人人做精品| 婷婷综合久久中文字幕蜜桃三电影| 91精品国产91久久久久久| 国产精品久久久久AV福利动漫| 久久久久久亚洲精品无码| 精品久久久久久亚洲| 97精品国产97久久久久久免费| 久久综合色区| 青青热久久国产久精品 | 久久亚洲精品无码VA大香大香| 青青草国产成人久久91网| 久久久久av无码免费网| 热RE99久久精品国产66热| 草草久久久无码国产专区| 久久国产乱子伦精品免费强| 国内精品久久久久影院老司| 久久精品亚洲乱码伦伦中文| 久久中文字幕一区二区| 久久久久四虎国产精品| 99久久精品毛片免费播放| 99国产精品久久| 久久99精品久久久久久久久久| 国产亚洲欧美精品久久久| 亚洲午夜久久久久妓女影院| 久久精品国产精品亚洲精品 |