二級(jí)制找1

運(yùn)算符

  • &:0&0=0 ,1&0=1,0&1=1,1&1=1
  • |:0|0=0,0|1=1,1|0=1,1|1=1
  • ^ :00=0,10=1,01=1,11=0

左移運(yùn)算符
m"<<"n,左移n位,左邊的n位被丟棄,同時(shí)最右邊補(bǔ)上n個(gè)0
比如

00001010<<2==00101000
10001010<<3==01010000

右移運(yùn)算符m>>n表示右移n位。右移n位的時(shí)候,最右側(cè)n位被丟棄。單右移時(shí)處理最左邊位的情形要復(fù)雜一點(diǎn),如果數(shù)字是一個(gè)無(wú)符號(hào)數(shù)值,則用0填補(bǔ)最左邊的n位。如果數(shù)字是一個(gè)有符號(hào)數(shù)值,則右移之后再最左邊補(bǔ)上n個(gè)0,如果數(shù)字原先是負(fù)數(shù),則右移之后再最左邊補(bǔ)上n個(gè)1.

00001010>>2=00000010
10001010>>3=11110001

請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù),輸入一個(gè)整數(shù),輸出該數(shù)的二進(jìn)制中表示1的個(gè)數(shù)。例如把9表示成二進(jìn)制數(shù)是10001,有2位是1,。因此如果輸入9,該函數(shù)輸出2
可能引起死循環(huán)的解法
--
先判斷整數(shù)二進(jìn)制表示中最右邊數(shù)是不是1,接著把輸入的整數(shù)右移以為,此時(shí)原來(lái)處于右邊數(shù)的第二位被移到最右邊,再判斷是不是1.這樣每次移到一位,直到整個(gè)整數(shù)變?yōu)?為止。判斷是不是1 則用&符號(hào)

    //尋找一個(gè)數(shù)字中的二級(jí)制中的1有幾個(gè) 可能有死循環(huán)的解法
    public int tester(int n) {
        int count = 0;
        while (n != 0) {
            if ((n & 1) == 1) {
                count++;
            }
            n = n >> 1;
        }
        return count;
    }

幾個(gè)面試問(wèn)題:如果把整數(shù)右移一位和整數(shù)除以2在數(shù)學(xué)上是等級(jí)的,那上面的代碼可以把右移運(yùn)算換成除以2么? 答案是否定的。因?yàn)橛|發(fā)的效率比移位運(yùn)算要低得多,在實(shí)際編程中盡可能使用移位運(yùn)算符替代乘除法
如果函數(shù)中輸入一個(gè)負(fù)數(shù)如:0x80000000,則會(huì)出現(xiàn)的情況,把負(fù)數(shù)右移以為的時(shí)候,并不簡(jiǎn)單的把高位1移到第二位變成0x4000000,而是0xC0000000。這是因?yàn)橐莆磺笆莻€(gè)負(fù)數(shù),仍然要保證移位后是個(gè)負(fù)數(shù)因此移位后的最高位會(huì)設(shè)為1。如果一直做右移運(yùn)算,最終會(huì)變成0xfffffffff而陷入死循環(huán)

常規(guī)解法

可以不右移輸入的數(shù)字。首先把n和1做&運(yùn)算,判斷最低位是不是1,然后左移

  //常規(guī)解法
    public static int tester2(int n) {
        int count = 0;
        int flag = 1;
        while (n != 0) {
            if ((n & flag) == 1) {
                count++;
            }
            n = n >> 1;
        }
        return count;
    }

另類解法

在分析算法前,先分析把一個(gè)數(shù)減去1,的情況,如果一個(gè)整數(shù)不為0,那么該整數(shù)的二進(jìn)制表示中至少有一位是1。先假設(shè)這個(gè)數(shù)的最右邊一位是1,那么減去1時(shí),最后一位變成0,而其他所有位都保持不變,也就是最后一位相當(dāng)于取反操作,由1變成0,接下來(lái)假設(shè)最后一位不是1而是0的情況,如果該整數(shù)的二進(jìn)制表示中最右邊1位于第m位,那么減去1,第m位由1變成0,而第m位之后的所以0都變成1,整數(shù)中第m位之前的所以位保持不變。舉個(gè)例子:一個(gè)二級(jí)制數(shù)1100,它的第二位是從最右邊數(shù)起的一個(gè)1,減去1后,第二位變成0,它后面的兩位變成1,而前面的1保持不變,因此是1011.
在前面兩種情況下,我們發(fā)現(xiàn)把一個(gè)整數(shù)減去1,都是把最右邊的1變成0,如果它的右邊還有0的話,所以0變成1,而它左邊所以位都保持不變,接下來(lái)我們把一個(gè)整數(shù)和它減去1的結(jié)果做位與運(yùn)算,相當(dāng)與它最右邊的1變成0,還是以前面的1100為例,它減去1的結(jié)果是1011,我們把1011與1100做與運(yùn)算,得到的結(jié)果是1000,我們把1100最右邊的1變成0,剛好是1000
分析總結(jié)
--
把一個(gè)整數(shù)減去1,在和原整數(shù)做與運(yùn)算,會(huì)吧該整數(shù)最右邊的一個(gè)1變?yōu)?,那么一個(gè)整數(shù)的二進(jìn)制表示中有多少個(gè)1,就可以做多少次這樣的操作。

public static int count(int n){
         int num = 0;
         while(n!=0){
             n = n&(n-1);
             num++;
         }
         return num;
     }

左移的循環(huán)次數(shù)等于整數(shù)二進(jìn)制的位數(shù),32位的整數(shù)需要32次,而上述的次數(shù),取決于整數(shù)中有幾個(gè)1,就循環(huán)幾次

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本章將會(huì)介紹 模塊和源文件訪問(wèn)級(jí)別訪問(wèn)控制語(yǔ)法自定義類型子類常量、變量、屬性、下標(biāo)構(gòu)造器協(xié)議擴(kuò)展泛型類型別名位運(yùn)算...
    寒橋閱讀 1,000評(píng)論 0 2
  • 高級(jí)運(yùn)算符(Advanced Operators) 本文參考自蘋(píng)果官方文檔Advanced Operators本頁(yè)...
    果啤閱讀 1,704評(píng)論 1 5
  • 高級(jí)運(yùn)算符 文檔地址 作為 基本運(yùn)算符 的補(bǔ)充,Swift 提供了幾個(gè)高級(jí)運(yùn)算符執(zhí)行對(duì)數(shù)傳值進(jìn)行更加復(fù)雜的操作。這...
    hrscy閱讀 913評(píng)論 0 2
  • 我真是無(wú)語(yǔ)了,從昨晚碼到現(xiàn)在的福利,居然發(fā)不出去,秒屏蔽,說(shuō)我文有問(wèn)題就算了,我7點(diǎn)多發(fā)個(gè)微信小劇場(chǎng)居然也被秒屏蔽...
    陸菱歌閱讀 8,321評(píng)論 0 9
  • 你說(shuō)網(wǎng)名不換,簽名不換,頭像不換,因?yàn)檎也坏礁玫摹?我兩年后可不可以成為你認(rèn)為的最好呢。 我好難過(guò),可我還會(huì)努力...
    影繁閱讀 196評(píng)論 0 0

友情鏈接更多精彩內(nèi)容