Bit Tricks (位運算技巧)

2021-10-03 06:37:38 字數 4556 閱讀 3773

技巧?是的,你沒有看錯!聰明的程式設計師總是喜歡這種東西。一點點讓我的生活變得如此輕鬆,以至於我總是喜歡談論它們!如果您不熟悉它或感到困難,那麼不用擔心,您來對地方了!本文旨在使您的旅途更輕鬆。

相信我,您一定會喜歡這篇文章。因此,讓我們開始吧!

位?這些是什麼?好吧,對於某些人來說,它是0和1,即二進位制數字。直到一天以前,我都一直有這種感覺,我們的一位教授告訴我們,他們具有特殊的含義。二進位制數字0和1表示數字電子裝置中的兩個狀態。二進位制0代表off狀態,而二進位制1代表on狀態。

您可能在想,當這篇文章是程式設計文章時,為什麼我要談論電子產品。各位天才程式設計師不僅是**,他們還了解計算機系統的內部工作。

在計算機系統中,所有內容都以二進位制格式表示,即以0和1的形式表示。因此,現在,當我們將數字儲存在計算機的記憶體中時,計算機實際上將儲存該數字的二進位制表示形式。數字5將作為二進位制101儲存在記憶體中。

讓我們談談幾個數字的位表示形式:

0 = 0 1 = 1 2 = 10 3 = 11 4 = 100 5 = 101 6 = 110 7 = 111 8 = 1000

依此類推。

我希望您已經知道如何將十進位制轉換為二進位制。

因此,繼續前進,您是否發現任何模式或特殊之處?

好吧,如果您仔細觀察,您會發現:

所有奇數(例如1,3,5等等)都設定了最後一位。我的意思是他們的最後一位是1。

所有偶數(例如0、2、4、6等)的最後一位均未設定。說最後一位未設定,是指他們的最後一位是0。

所有為2的冪的數字在其二進位制表示中僅設定了最左邊的位。(2 = 10、4 = 100、8 = 1000)。

如果數字n是2的冪,則n-1的二進位制表示形式將全為1,並且其二進位制表示形式的位數將比n的二進位制表示形式少一位。 8 = 1000和7 = 111)

我們可以從上方找到許多這樣的觀察結果,但是目前,這些觀察結果足以讓我們繼續前進。

現在的問題是,如何輕鬆地獲取數字的二進位制表示形式。好吧,如果我們要列印給定數字的二進位制形式,則必須了解稱為shifting的東西。相信我,它們是無害的,它們一定會使我們的工作變得容易,所以很高興了解它們!

有兩個這樣的運算子。

當我們寫:

同樣,對於右移:

所以基本上,如果我寫這樣的話:

正常的左移表示在數字的二進位制表示形式的末尾附加i個零。正常的右移意味著從數字中將最右邊的位截斷i次,並在開頭新增零。

如果您注意到的話,這裡有乙個非常細微的觀察結果,當我們將數字4左移1個位置時,我們得到8,即4乘以2的結果。類似地,當我們將數字4右移1個位置時,我們得到2,即正是我們將4除以2得到的結果。

因此,我們可以宣告:

當我們將數字左移1位時,實際上是將數字乘以2。當我們將數字右移1位時,實際上是將數字除以2。

同理,如果我們將數字i左移,那意味著我們將數字乘以2,即i倍。同樣,如果我們將數字i右移,那意味著我們將數字除以2,即i倍。

我們還沒有完成。我們需要掌握更多操作員的基本知識。我想,您已經了解它們。

or(表示為|),如果兩個運算元中的任何乙個都不為零,則返回1,基本上執行聯合操作。

and(表示為&),如果所有運算元都不為零,則返回1,基本上執行相交運算。

xor(表示為^),對於1的奇數返回1,或者可以說,當兩個運算元保持相同的值時,它返回0。

通過示例進行解釋,如果您已經知道這三個運算子的工作原理,則可以跳過本部分:

a =

1001,b =

0101

a | b =

1101

a&b =

0001

a ^ b =

1100

恭喜大家!我們從字面上涵蓋了位操作操作所使用的所有基本概念。可是等等!我們還沒有完成。

讓我們嘗試一些現實世界中的問題,並了解如何使用這種出色的技術解決它們。位操作將使**更短,使我們的工作更加輕鬆。

設數字為10(十進位制)。10 = 1010(二進位制)。我們假定最左邊的位是位置1,則從右邊2開始的位是1。天真的程式設計師肯定會將數字從十進位制形式轉換為二進位制形式,然後將其列印在所需位置。

儘管這種方法對於少量數字可以很好地工作,但是假設我們有乙個非常大的數字,例如103076。如果我們開始將其從十進位制轉換為二進位制,則會消耗大量時間和記憶體!但是您不必為此擔心。現在,您是乙個更好的程式設計師,並且知道一些技巧可以做到!

記住,我們討論了移位運算子。我們的方法將包括在數字和左移給定位置的1之間進行按位與運算,以從數字中提取該位置的位。如果我們將數字1左移1,我們得到10。給定的數字是1010。如果我們在數字1010和10之間執行「與」運算,該怎麼辦?

1010&10

=10

結果為非零,這表明1010的位置2的位必須為非零,因為當我們將其與1進行與時,結果的第二個位置將為1。

如果該數字為1000,並且我們將其與10相與,則結果將為1000&10 = 0000,清楚地說明該位置2的位未設定。

要檢查某個位在給定位置上是設定還是未設定,請執行此操作

結論:如果 數字 &(1 <<(位置-1))!= 0:設定位

101101 ^ 111111 => 010010(記住xor操作,它返回1表示奇數個數)

結論:通過位1的xor可以切換原始位。

好了,我們已經討論過了。當數字的二進位制表示形式只有乙個1時,數字就是2的冪,也是最左邊的一位。

我們可以採取另一種方法。假設我們必須檢查數字8。8= 1000 和 8–1 = 7 = 0111

如果我們將數字與1相與,則將得到0,如上例所示。

但是如果number = 3,number-1 = 2

3 = 11(bin) 和 2 = 10(bin)=> 11&10 = 10 ,10!= 0

結論:如果number&(number-1)== 0,則number為2的冪

您必須將陣列元素的出現頻率儲存在某個位置。但是,問題陳述中的約束表示沒有使用任何額外的空間。好吧,如果您不了解位操作的知識,那麼您真的不能不使用任何額外的空間。到那時,我想您可能已經猜到了我們應該執行的位操作。是! 是xor。

我個人認為,xor是一項非常有用且功能強大的操作。您應該始終首先考慮是否可以使用xor解決問題。

因此,讓我們看看xor如何解決這個問題:

a =

,您會看到答案應該是2,因為它是唯一缺少配對的元素。1=

1,2=

10,3=11

1^1=

02^2

=10^10

=003^

3=11^

11=00

當我們將元素與自身進行xor運算時,結果為0。如果我們對所有陣列元素進行xor,那麼每個重複對的xor將為零,並且我們將只剩下一次出現的元素。

1 ^ 2 ^ 3 ^ 1 ^ 3 =(1 ^ 1)^(3 ^ 3)^ 2 = 0 ^ 0 ^ 2 = 2

結論:元素與自身的異或結果值為零。

您可以使用的第一種方法是通過使用移位運算來計數數字的每個設定位。

第二種方法:您可以使用and操作解決此問題。

有一種稱為brian kernighan演算法的演算法。它指出,如果我們對數字1進行「與」運算,我們實際上將其最右邊的位設定為0。因此,繼續執行直到數字變為零為止。

number = number&(number-1),直到number!= 0,然後在每一步遞增計數器。

example:

number =11=

1011

number-1=

10=1010

count =

0number =

1011

&1010

=>

1010

and count=

1number =

1010

&1001

=>

1000

and count=

2number =

1000

&0111

=>

0000

and count=

3由於數字現在為零。因此停止。所以在數字11的二進位制1011中1出現了3次

// 在程式中 輸入: 00000000000000000000000000001011 輸出: 3

inthammingweight

(int n)

return sum;

}

結論:數字中的設定位數:number =number&(number-1),直到number!= 0,並在每一步遞增計數器。最後返回次數。

number of bits = floor(log(number)/ log(2))+1

位運算技巧

1.lowbit x 實現 int lowbit int x 這個函式用來求數中二進位制位中最低位的1 完整求法 log2 lowbit x 需要注意的是,答案的範圍是0 30,因為31位是符號位,求出來的值為負數,原因如下 設x 0x8000 0000,那麼設res lowbit x 0x8000...

位運算技巧

數字和1相與 判斷奇偶 x 1 1 奇數 x 1 0 偶數 不用其他空間交換兩值 a a b b a b a a b 或a a b b a b a a b a 0 a a a 0 不用其他空間找陣列中唯一成對的那個數 int b 0 for int i 1 i 10 i int a 10 for i...

位運算技巧

1.或 符號 比較兩個數的每一位,只要有乙個數在這一位上為1,所得的新數在這一位上就為1,否則為0。2.與符號 比較兩個數的每一位,只有兩數這一位同時為1時所得新數為1,否則為0。3.異或 符號 比較兩數的每一位,如果一樣所得新數這一位就是0,不一樣就是1。4.取反 符號 0變1,1變0。5.移位 ...