日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

位运算n=(n-1)快速统计二进制1的个数

發布時間:2025/1/21 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 位运算n=(n-1)快速统计二进制1的个数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

看到一篇博客,發現n&=(n-1)竟然能夠快速統計二進制1的個數,經過博主同意特此拿來分享一下。


首先,分析一下該式子,先可以簡化為

n=n&(n-1);

我們先做一個實例,

n12345678
十進制12345678
二進制00010010001101000101011001111000

我們先試著求7中二進制1的個數k

? ? ?0111

& ?0110

-------------

? ? 0110(6)

然后對其結果繼續進行上述操作

? ? 0110

& 0101

-------------

? ? 0100(4) ? ?

繼續上述操作

? ? 0100

& ?0011

-------------

? ? 0000

結束操作。

至此,我們可以發現,每次&操作后,0111(7)的二進制數中最右邊的1都被消除1個,

第一次&操作后,結果為0110

第二次&操作后,結果為0100

第三次&操作后,結果為0000

而k恰好與&操作的次數是相同的。那么我們可以猜測這兩者必然存在直接關聯關系。

不過,當二進制數中1的位置不連續,中間有若干個0這個公式也能“跳過”0,直接統計1的個數嗎?

下面我們在舉個實例37(0010 0101)這個比較有代表性

n12345678
十進制12345678
二進制00010010001101000101011001111000
同樣進行&操作,

? ? ?100101

& ? 100100(36)

----------------------

? ? ?100100(36) ? ?

繼續重復上述操作

? ? ?100100

& ? 100011

--------------------

? ? ?100000(32)?

繼續重復上述操作

? ? ?100000

& ? 011111

--------------------

? ? ?000000

結束。

到這里,我們會得出一個結論,

1的位置無非就三種情況,頭和中間、尾部

a.在尾部的情況

? ? 當末尾是1的時候(奇數),與前一個數(偶數)進行&操作后,結果必為0,末尾的1消除

b.在頭部的情況

? ? 當1只在頭部的時候,其余位上都為0.類似8(1000),4(0100),與前一個數(全1,7(0111),3(0011))進行&操作時,結果必為0.

c.在中間的情況

? ? ?無非也是上述兩種情況的遞歸。保證末尾位為0,因為之前已經處理過尾部的情況了。

? ? ?比如,尾部是*0010結尾,*0100結尾,*1010結尾,*11010結尾。他們對應的前一個數分別是:*0001,*0011,*1001,*11001。(*代表左邊還有若干個0和1)

? ? ?0010

& ? 0001

-------------

? ? 0000

結束。

? ? ?0100

& ? 0011

-------------

? ? ?0000

結束。

? ? ?1010

& ? 1001

--------------

? ? ?1000(消除最右邊的1,下一步進行第二種情況的處理)

結束。

? ? ? 11010

& ? ?11001

---------------

? ? ? 11000(消除最右邊的1,下一步進行第一種情況的處理)

結束。


--------------------------------分割線-------------------------------------

到這里,我們就可以看出,每次在最右的1設置一個flag的話,

當它(i)與它前一位(i-1)進行&操作時,對flag左邊的1是沒有影響的,每次得到的結果,就會將flag位置及右邊所有的數置為0.

例如:11010&11001 ==11000(24)

那么,結束條件是什么呢?

? ? ? 那就是當&操作后的結果為0,循環結束。


好啦,分析就到這里。下面附上源代碼供看官們欣賞哈~

  • for (int count =0; n; ++count)
  • {
  • n &= (n -1) ; //每次消除最右邊的1,當n為0結束
  • }
  • 另一種寫法:
  • count=0
  • while(k){
  • k=k&(k-1);
  • count++;
  • }









  • 總結

    以上是生活随笔為你收集整理的位运算n=(n-1)快速统计二进制1的个数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。