educoder 二進制數據的位運算_二進制與位運算實用操作匯總(基礎篇)

位運算是最高效而且占用內存最少的算法操作,但也是最難看懂的操作。然而,關于位運算的用法,筆者查了許多資料,似乎都沒有找到詳細而系統的講解資料。筆者對位運算的操作相當感興趣,因此斗膽嘗試對位運算來一個的總結。

本文先從基本概念出發,然后從基本概念推導出基礎應用,然后再到算法題實戰。層層推進,逐步迭代。

本人水平有限,如有勘誤,敬請指正。

說明:本文會以Python的交互環境來做代碼演示。關于本文的約定:非代碼塊中的二進制數以下標x來表示進制數,如十進制數15,用二進制表示為

,而用十六進制則表示為

所有代碼塊中的二進制數字都以0b開頭,比如十進制數15,用二進制表示為0b1111;

有時候需要更直觀地表示,會使用豎式表示,如兩個二進制數的and操作表示為:

所有代碼塊中的十六進制數字都以0x開頭,比如十進制數255,用十六進制表示為0xff;

bin()函數,是Python中把十進制轉換為二進制的轉換函數;

所有的位運算操作的命名均用英文命名,以增加辨識度。

概念篇

and 操作,操作符“&”

定義:稱為按位與運算符。它對整型參數的每一個二進制位進行布爾與操作,即兩個對應的二進制位同時為1時,才等于1。

or 操作,操作符“|”

定義:稱為按位或運算符。它對整型參數的每一個二進制位進行布爾或操作,即兩個對應的二進制位,任意一個為1時,就等于1。

xor操作,操作符“^”

定義:稱為按位異或運算符。它對整型參數的每一個二進制位進行布爾異或操作,即兩個對應的二進制位,有且僅有一個為1時,才等于1。

not操作,操作符“~”

定義:稱為按位非運算符。它是一個單運算符,對運算數的所有二進制位進行取反操作。

shl操作,操作符“<

定義:稱為按位左移運算符。它把第一個運算數的所有二進制位向左移動第二個運算數指定的位數,而新的二進制位補0。將一個數向左移動N個二進制位相當于將該數乘以2的N次方,比如:

shr操作,操作符“>>”

定義:稱為按位右移運算符。它把第一個運算數的所有二進制位向右移動第二個運算數指定的位數。為了保持運算結果的符號不變,左邊二進制位補 0 或 1 取決于原參數的符號位。如果第一個運算數是正的,運算結果最高位補 0;如果第一個運算數是負的,運算結果最高位補 1。將一個數向右移動N個二進制位相當于將該數除以2的N次方,比如:

(總是向負無窮方向取整)。

原理篇

進制轉換

進制之間的轉換其實是個數學問題,在實際應用中,我們基本上無需操心。因此這里想說的不是計算問題,而是邏輯問題。二進制與十六進制有著天然的聯系——每四個二進制位可以代表一個十六進制位:

由上圖可見,如果說二進制轉十進制還要稍稍心算一下的話,那二進制轉十六制可以馬上得出。只要記住了一個十六進制位與四個二進制位的對應關系就好了。同理,八進制位與二進制的關系是,每三個二進制位對應一個八進制位,但實踐中,八進制并不常見,因此點到即止。

那么,為什么二進制與十六進制在實踐中更常見呢?這是與內存的儲存單位有關。

字節與二進制數的關系

對于計算機而言,最小的儲存單位是一個字節,英文為byte。byte既是一個單位,也是一種數據類型(關于數據類型的解釋,可查閱C/C++、JAVA等靜態類語言的相關資料,本文不作介紹)。對于一個byte的數據,用了八個二進制位去儲存數據,因此能正好用兩個十六進制位來省略表示(比十進制還少寫一位)。這就是為什么在實際操作中,二進制與十六進制更常見的原因。

二進制運算符的操作范圍

筆者查閱了許多二進制運算的相關資料,似乎都忽略了對這一點的介紹。二進制運算符的作用范圍與參與運算的變量的數據類型有關,比如以JAVA為例:對于byte類型變量,由于byte以8-bit(8個二進制位)表示,因此相應的位運算符的作用范圍就是8-bit;

對于int類型變量,由于int以32-bit表示,因此位運算符的作用范圍就是32-bit;

假如兩個大小不一的數據類型進行操作,那位運算的作用范圍會以較大的數據類型作為基準范圍。

二進制數的符號

有了數據類型的范圍限定,因此才有了高位、低位、符號位的概念。高位,指在數據類型限定范圍內靠左的二進制位;

低位,指在數據類型限定范圍內靠右的二進制位;

符號位,指在數據類型限定范圍內最左邊的一個二進制位,符號位為0表示正數,1表示負數。(除了C語言存在無符號的值類型外,絕大部分語言的值類型都默認為有符號的數值類型)

因此,假如一個byte范圍內的整數,提升為一個int范圍內的整數,由于二進制位數的范圍大了,必然需要進行補位,因此:當原byte整數為正數時,提升為int類型時,補位全部以0補位;

當原byte整數為負數時,提升為int類型時,補位全部以1補位;

為什么要這樣做?因為這樣才能保證數值在范圍提升后,原值的十進制數不變。以下來看看JAVA的驗證代碼:

// byte類型的值范圍是[-128,127]byte a = (byte) -55; //由于值在byte范圍內,因此強制轉換縮小變量內存范圍不會改變原值byte b = (byte) 100;

System.out.println(Integer.toBinaryString(a)); //輸出(二進制數):11111111111111111111111111001001System.out.println(Integer.valueOf(a)); //輸出:-55(重新提升范圍,值不變)System.out.println(Integer.toBinaryString(b)); //輸出(二進制數):1100100(高位的0會被省略顯示)System.out.println(Integer.valueOf(b)); //輸出:100

二進制下的負數表示法

對于一個十進制的負數,我們經常把它看作是一個數加一個負號;然而對于二進制負數來講,卻不是一堆二進制位數加一個符號位。

二進制的正數與負數之間的關系更像是“進位”的關系。以下我們以一個byte值來舉例:

如上所述,byte的數值范圍是[-128,127]。

為了讓表示更清楚,筆者特意把符號位隔開。留意從0到-1,由于非符號位全部為0,已經沒有東西可減,但假如我們假設從更高的位借來了一個1,這樣就能讓

了;有了-1,那

就可以繼續成立了……直到把除符號位之外的位全部減完,這時十進制數就相當于-128。因此,八位二進制數可以表達的數為

個,即[-128,127]。

二進制數的性質

由以上的二進制數變化規律,我們可以發現二進制數有以下性質:~x = -x - 1:從以上0與-1的按位關系可以看到,兩者的二進制位正好取反;此規律能推廣到1與-2,2與-3……等等。因此,該性質是not操作中最常使用的性質。

(~x)&x = 0:任意數與它的取反數的and操作結果為0。

(~x)|x = -1:任意數與它的取反數的or操作結果為-1。

(~x)^x = -1:任意數與它的取反數的xor操作結果為-1。

x|0 = x:任意數x與0的or操作結果為x自己。

x^0 = x:任意數x與0的xor操作結果為x自己。

x^y^y = x:任意數x與任意數y進行兩次xor操作結果為x自己。

與四則運算一樣,位運算也有它自己的定律。因此,我們有必要先熟悉并證明一下這些定律。

定律篇

and操作

交換律,a&b = b&a

證明:略(因為顯然易見)

結合律,(a&b)&c = a&(b&c)

證明:只要證明一個二進制位,便能推廣到N個二進制位。

(1&0)&0 = 1&(0&0) = 0;

1&1&0 = 1&(1&0) = 0。

or操作

交換律,a|b = b|a

證明:略

結合律,(a|b)|c = a|(b|c)

證明:只要證明一個二進制位,便能推廣到N個二進制位。

(1|0)|0 = 1|(0|0) = 1;

1|1|0 = 1|(1|0) = 1。

xor操作

交換律,a^b = b^a

證明:略

結合律,(a^b)^c = a^(b^c)

證明:

not操作

結合律,a = ~(~a)

證明:略

shl操作

shr操作

繼續深入傳送門:黃偉亮:二進制與位運算實用操作匯總(應用篇)?zhuanlan.zhihu.com

參考資料:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537073.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537073.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537073.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

企業為什么要做SEO,它的重要性有哪些?

對于SEO工作而言&#xff0c;我們知道一個網站做SEO的基礎訴求就是讓用戶和搜索引擎更好的理解網站內容&#xff0c;雖然隨著搜索引擎算法技術的迭代&#xff0c;目前SEO面臨更大的挑戰與競爭&#xff0c;但基于搜索營銷&#xff0c;它目前仍然顯得十分重要。 那么&#xff0…

白話說編程之java線程

白話說編程之java線程線程和進程&#xff1a;進程&#xff1a;線程&#xff1a;線程和進程的區別&#xff1a;詳解多線程:并發為什么使用并發并發的執行原理并行線程的五種狀態&#xff1a;創建狀態&#xff1a;就緒狀態&#xff1a;運行狀態&#xff1a;阻塞狀態&#xff1a;死…

powerdesigner顯示工具面板_photoshop教程-畫筆工具預設與選項設置

定義畫筆預設在打開的“畫筆”面板中&#xff0c;單擊左側的“畫筆筆尖形狀”名稱&#xff0c;可顯示筆尖形狀圖案。單擊“畫筆”面板左側其他不同的選項名稱&#xff0c;在右側就會顯示其對應的調節項。只單擊不同選項前面的方框&#xff0c;可使此選項有效&#xff0c;但右側…

C#屬性的聲明和使用演示源碼片段

工作閑暇時間&#xff0c;將代碼過程重要的一些代碼做個收藏&#xff0c;如下代碼是關于C#屬性的聲明和使用演示片段的代碼&#xff0c;應該對碼農有一些好處。 using System; class Person {private string myName "N/A";private int myAge 0;public string Name{g…

深入理解== 和 equals 的區別

深入理解 和 equals 的本質區別簡介區別&#xff1a;圖解&#xff1a;注意點&#xff1a;源碼分析&#xff1a;總結分享一波:程序員賺外快-必看的巔峰干貨簡介 初學者常常被" “和‘equals ’所折磨&#xff0c;為什么&#xff0c;因為他們的大概意思相同&#xff0c;都是…

rsem比對_RSEM方法比對和表達量計算

分析模塊&#xff0c;封裝了Trinity程序包中的“align_and_estimate_abundance.pl”腳本&#xff0c;進行原始數據與轉錄本序列的比對和表達量計算。其中&#xff0c;核心程序為&#xff0c;Bowtie或Bowtie2進行原始數據與轉錄本序列的比對&#xff0c;RSEM根據比對結果進行表達…

java sleep和wait區別

為什么80%的碼農都做不了架構師&#xff1f;>>> 關于sleep和wait區別解析&#xff1a; sleep只是釋放CPU資源&#xff0c;并不釋放資源鎖對象&#xff0c;wait是會釋放掉資源鎖對象。 比如&#xff0c;有個鎖對象object&#xff0c;線程1和線程2都會鎖住object對象…

u8轉完看不到菜單_web網頁有錯誤,無法看到操作菜單-用友U8

文章摘要&#xff1a;本文提供在用友U8V8.51erp軟件財務會計管理的WEB財務模塊中客戶在使用WEB功能時&#xff0c;沒有使用默認的設置&#xff0c;是將WEB功能設置在自己的網站上面&#xff0c;訪問WEB功能沒有問題&#xff0c;界面出來了&#xff0c;輸入用戶名、密碼、選擇帳…

.Net Core 項目引用本地類庫方式(二)

上篇文章有詳細的介紹.Net Core 項目中引用本地類庫通過打包&#xff0c;然后Nugety引用方式&#xff0c;這里再介紹一種引用包的方式 轉載于:https://www.cnblogs.com/wangshitou/p/10283800.html

深入理解equals和hashCode關系和區別

深入理解equals和hashCode關系和區別直入主題&#xff1a;區別&#xff1a;1.他們判斷對象相同的方式不一樣&#xff1a;2.他們判斷對象是否相等的準確率不一樣&#xff1a;改寫equals時總是要改寫hashcode分享一波:程序員賺外快-必看的巔峰干貨為什么要說equals和hashCode這兩…

lol韓服游戲內設置_韓服LOL進去了還不能玩?教你如何玩韓服!

領取免費韓服LOL安全號&#xff0c;百度搜索韓服LOL微博關注即可&#xff01;上圖錯誤為常識性錯誤&#xff0c;LOL韓服游戲的安裝文件路徑有中文所導致的錯誤 解決方法&#xff1a;將安裝路徑里的中文改成英文即可 舉例 包含中文漢字的文件夾都是錯誤的 Program FilesLOL韓服 …

Jdk 和 jre 的 關系和區別

Jdk 和 jre 的 關系和區別 區別&#xff1a; JDK&#xff1a;是Java Development Kit 的簡稱–>翻譯過來就是&#xff1a;Java 開發工具包。是程序員使用java語言編寫java程序所需的開發工具包&#xff0c;是提供給程序員使用的。 JRE&#xff1a;是Java Runtime Environm…

OpenCV-Python入門教程7-PyQt編寫GUI界面

前面一直都是使用命令行運行代碼&#xff0c;不夠人性化。這篇用Python編寫一個GUI界面&#xff0c;使用PyQt5編寫圖像處理程序。包括&#xff1a;打開、關閉攝像頭&#xff0c;捕獲圖片&#xff0c;讀取本地圖片&#xff0c;灰度化和Otsu自動閾值分割的功能。 使用Qt Designer…

spark 廣播變量大數據_大數據處理 | Spark集群搭建及基本使用

點擊藍字關注我前面用了一篇文章詳細的介紹了集群HDFS文件系統的搭建&#xff0c;HDFS文件系統只是一個用于存儲數據的系統&#xff0c;它主要是用來服務于大數據計算框架&#xff0c;例如MapReduce、Spark&#xff0c;本文就接著上一篇文章來詳細介紹一下Spark集群的搭建及Spa…

如何將本地項目上傳到gitee

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

oracle dg 備庫未設置convert參數導致ORA-01111,ORA-01110

2019獨角獸企業重金招聘Python工程師標準>>> 查看trace 文件&#xff1a; MRP0: Background Managed Standby Recovery process started (amls) started logmerger process Sun Jan 20 07:55:53 2019 Managed Standby Recovery starting Real Time Apply MRP0: Back…

git回退歷史版本無法上傳_Git系列教程(二):版本庫中添加文件、版本回退

Git系列教程(一)&#xff1a;簡介、安裝、配置我們學習了分布式和版本控制系統的概念、Git具有的8個功能以及如何在Windows上安裝Git、進行相關配置并創建版本庫。Git版本庫中添加文件Git 的工作就是創建和保存你的項目的快照及與之后的快照進行對比。我們編寫一個readme.txt文…

nginx反向代理配置如何去除前綴

使用nginx做反向代理的時候&#xff0c;可以簡單的直接把請求原封不動的轉發給下一個服務。設置proxy_pass請求只會替換域名&#xff0c;如果要根據不同的url后綴來訪問不同的服務&#xff0c;則需要通過如下方法&#xff1a; 方法一&#xff1a;加"/"** server {l…

「作文素材詳解」寫作必知篇:語言優美不是作文第一要求

語言優美不是作文第一要求“教孩子寫作文&#xff0c;老師家長應該先提升自己。”“語言優美不是作文的第一要求。”“如果教孩子寫漂亮的違心話&#xff0c;會害了他一輩子。”日前&#xff0c;著名作家肖復興來到體育東路小學&#xff0c;與廣州的一線語文教師交流&#xff0…