0基礎學演算法 第七彈 位運算
今天要講的內容主要分為兩個大塊,一個呢就是位運算,另一個呢就是關於二進位制的原碼反碼補碼,位運算的應用也算是比較多的了,進行位運算有時候可以省略不少事情呢,當然,也不是說不會位運算就會天崩地裂,畢竟事實上,在學位運算之前,我都是用其他方法來強制性模擬位運算(當時我並不知道什麼是位運算)不過多學一些也是好的,省事兒,而且更快
一,二進位制的原碼反碼和補碼
相信二進位制沒有人不熟悉的,逢二進一,一個二進位制數由0和1組成,他的最高位就是他的正負符號,0是正數,1是負數,例如10001000,這就是一個負的二進位制數,當然最高位是0就是正數
原碼之所以叫做原碼,必然是因為它就像是萬物之源,補碼、反碼都是在他的基礎上變化的,當最高位是0的時候,也就是正數的時候,原碼==反碼==補碼
以下關於反碼及補碼的概念是基於最高位是1的情況(負數的情況)
反碼,顧名思義,是原碼顛倒過來的樣子,除了最高位表示負號的那個“1”不變以外,其他的數位上的數 全部取反,1變0,0變1,假設原碼為1001010100,它的反碼就是1110101011,再假設原碼是0111001,它的反碼就是0111001,是不是有點奇怪,哈,我前面說過了,當原碼是正數的時候,原碼==反碼==補碼
補碼,在原碼是正數的情況下是等於原碼或者反碼的,但是在負數情況下,他恰好是反碼加1,比如原碼是100000,反碼就是111111,補碼就是1000000
二,進入正題,位運算
在系統的講位運算之前,先給大家一張圖表,方便大家查詢
註明:位運算子號在c++中用法同算數運算子
首先是&
其實位運算不復雜,理解了就好,比如說&,把他理解成1代表true,2代表false,1&&2,明顯為false(2),2&&2明顯也為false(2),只有1&&1的時候才為true(1);
但是這是if語句裡面的判斷方法,而‘&’的運算方法是這樣的,比如1010&0011,運算過程如下圖
過程如右圖
至於|的話。。。就是上下兩個數只要有一個為1,結果就為1啦,如1100|0011=1111
‘~’!也比較好理解,做它的運算的時候,只需要傳一個二進位制數,針對每一位進行運算可以從在每一位上如~1001=0110;
^,亦或,算起來也比較簡單,只要兩位不相等,結果就為1,舉例,1001^0101=1100
我覺得有圖就不用我多講了吧/狗頭/滑稽
最後一組"<<"和”>>"這個是左移和右移的操作
請看
int型別的二進位制是32位的,而long long是64位,左移和右移
例如,給出一個標準的32的int型別00000000000000000000000000000001,當我們使用左移的時候,整體忘左移,並在後面補零
右移也相似,只不過是低位被擠掉了,高位補0
有一道題,可以通過位運算做的很簡便,但如果你不會位運算的話。。。就另當別論了
如果你不用位運算,你要寫很複雜的程式碼,但是用了,你就只要10行程式碼,如假包換(雖然我絕對不換)
題目連結→https://www.luogu.com.cn/problem/P1100
看到題目,很清晰了,首先錄入兩個字串,然後將它轉成二進位制,接著把前16位和後16位的數交換位置,最後結果轉成十進位制輸出!好,完美。。。
停!
今天利用我們學的位運算壓根不用這麼麻煩!
直接用上我們的左移"<<"和右移">>"啊!
只要左移後16位,右移前16位不就好了?
廢話不多說,大家請看最短程式碼!
#include<bits/stdc++.h> using namespace std; unsigned int x; int main(){ cin>>x;//錄入x cout<<((x<<16)|(x>>16));//將左移16位後的x和右移16位的x用或"|"將他們重新連起來 return 0;//完美 }
完美撒花