位操作符
- 位操作符都是最底層的操作,直接操作二級制數據,因此性能上比其他操作符要好,性能好,但是會導致代碼可讀性降低
- 二進制
- 二進制是計算技術中廣泛采用的一種數制。二進制數據是用0和1兩個數碼來表示的數。它的基數為2,進位規則是“逢二進一”,借位規則是“借一當二”,由18世紀德國數理哲學大師萊布尼茲發現。當前的計算機系統使用的基本上是二進制系統,數據在計算機中主要是以補碼的形式存儲的。計算機中的二進制則是一個非常微小的開關,用“開”來表示1,“關”來表示0。數字計算機只能識別0和1。簡單,易于電子方式的實現。
- 十進制轉二進制
- 用十進制數字除以2,取余數,用得到的結果繼續除以2,一直到1除以2,然后求倒序就是二進制了
- 例如:10,10/2 = 5 余 0 ;5/2 = 2余1;2/2 = 0;這時候除盡了,則進行最后一次計算,1/2除不開,直接等于1即可;最后組合余數為:0101,然后倒序就是1010,因此10轉為二進制就是1010了
- 因此,9的二進制就是9/2=4余1,4/2=2余0,2/2=0余0,1/2余1,得1001,倒序9的2進制就是1001
- 39的二進制就是:39/2=19余1,19/2=9余1,9/2=4余1,4/2=2余0,2/2=0余0,1/2余1,組合余數:111001,倒序,39的二進制就是100111
- 高位補0
- 在內存中某一個類型的值是有固定長度的,比如int類型的是32位的,10轉為二進制位1010,那么就會在1010前面補28個0,補為32位進行存儲
- 一般正數高位補0,負數高位補1
- 二進制轉十進制
- 按權相加法
- 10的二進制是1010,從右往左按下標來數,0的下標是0,1為1,0為2,1為3,把這些二進制中數字是1的下標當做2的冪進行相加,那么1010 = 0 + 2^1 + 0 + 2^3 = 0 + 2 + 0 + 8 = 10
- 9的二進制是1001,相應的1001 = 2^0 + 0 + 0 + 2^3 = 1 + 0 + 0 + 8 = 9
- 39的二進制是100111,相應的100111 = 2^0 + 2^1 + 2^2 + 0 + 0 + 2^5 = 1 + 2 + 4 + 0 + 0 + 32 = 39
- 符號位
- 正負號標記
- 負十進制轉二進制
- 以-10為例,先將整數部分進行二進制計算,余數為0101,倒序10的二進制為1010,高位補0補到8位得00001010,取反得到11110101然后加1,由于二進制中只有0和1,因此遇2要進一位,則-10轉為二進制位-11110110,負數高位補1
- 二進制負數轉十進制
- 以-10為例,負數二進制位11110110,先減1,0位不夠減,向前借一位,0往前借一位,得2,2減1得1,因此得到11110101,然后取反得到-00001010,這就是10的二級制了
- 小數轉二進制
- 小數點前面按照正負數轉換即可,把小數點前面的正數部分剝離開,補0,小數點后面的,每次乘以2,得到的結果取正數部分即可,然后拼接一起
- 例如:10.2,10轉為二進制為1010,剝離整數部分補0為0.2,0.2乘以2,為0.4,取整數部分0,0.4乘以2,得0.8,取整數部分0,0.8乘以2,得1.6,取整數部分1,現在整數部分有1了,記錄1,然后剝離出去,這個1不用轉二進制,即使轉也是1,然后留下0.6,繼續乘以2,得到1.2,剝離,得0.2,乘以2,得0.4,取整數部分……一直到夠32位或者到達指定位數或者小數部分為0,最終結果為:1010.00110011001100110011
- 例如:10.5,10轉二進制為1010,保留剝離,剩余0.5,0.5乘以2得1.0,取整數部分,小數部分為0,因此不需要繼續計算了,所以10.5轉為二進制結果為:1010.1
- 二進制小數轉十進制
- 先把整數部分和小數部分拆來,例如10.5的二進制為1010.1,拆為1010和0.1,然后整數部分按照二進制轉十進制正常轉換,小數部分0.1 =1 乘以 2 ^ -1 = 0.5,拼接后的10.5
- 例如:10.2轉為二進制位1010.00110011001100110011,整數部分轉為10,小數部分為0.00110011001100110011就等于:0 * 2^ -1 + 0 * 2^-2 + 1 * 2^-3 + 1 * 2^ -4 + 0 * 2^-5…… (對應小數位置的0或1) * 2 ^ -n(從左往右1 - n)
- 位操作是程序設計中對位模式按位或二進制數的一元和二元操作
- 在js中對64位(0-9 + a-z + A-Z + - + ~)的數值會轉為32位數值,計算完成在轉為64位,NaN和Infinity會被當做0來處理,這是由于轉換時存在的副效應,如果使用位操作符轉換非數字,則會先把其轉為Number類型,再進行轉換
- 按位非
- 用~表示
- 10的二進制位1010,補32位為00000000000000000000000000001010
- var num = ~10,表示非10的二進制,則對上面的32位二進制數字進行求反得:11111111111111111111111111110101
- 因此var num = ~10得 -11,本質上是對操作數的負值-1,相等于var num2 = -num - 1;
- 按位與
- 用&表示
- 先將兩邊的操作數轉為二進制,然后補齊32位,每一位進行比較,遇0返回0,都為1返回1
- 例:2 & 4,2轉為二進制為10,補齊00000000000000000000000000000010,4轉為二進制為100,補齊后為:00000000000000000000000000000100,每一位對應比較,按照上面規則,沒有對應的,全返會0,因此結果為00000000000000000000000000000000,也就是0
- 例2 & 3,2轉二進制為10,補齊00000000000000000000000000000010,3轉二進制為11,補齊后得到結果為:00000000000000000000000000000011,參照以上規則,1對應1返回1,有0返回0,則得到結果為:00000000000000000000000000000010,轉為十進制后,結果就為2
- 按位或
- 用|表示
- 先將兩邊的操作數轉為二進制,然后補齊32位,每一位進行比較,遇1返回1,都為0返回0
- 例:2 | 4,2轉為二進制為10,補齊00000000000000000000000000000010,4轉為二進制為100,補齊后為:00000000000000000000000000000100,每一位對應比較,按照上面規則,遇1返回1,因此結果為00000000000000000000000000000110,也就是十進制的6
- 例2 | 3,2轉二進制為10,補齊00000000000000000000000000000010,3轉二進制為11,補齊后得到結果為:00000000000000000000000000000011,參照以上規則,遇1返回1,都為0返回0,則得到結果為:00000000000000000000000000000011,轉為十進制后,結果就為3
- 按位異或
- 用^表示
- 先將兩邊的操作數轉為二進制,然后補齊32位,每一位進行比較,一個為1,一個為0返回1,都為1返回0,都為0返回0
- 例:2 ^ 4,2轉為二進制為10,補齊00000000000000000000000000000010,4轉為二進制為100,補齊后為:00000000000000000000000000000100,每一位對應比較,按照上面規則,因此結果為00000000000000000000000000000110,也就是十進制的6
- 例2 ^ 3,2轉二進制為10,補齊00000000000000000000000000000010,3轉二進制為11,補齊后得到結果為:00000000000000000000000000000011,參照以上規則,則得到結果為:00000000000000000000000000000001,轉為十進制后,結果就為1
- 左移
- 由<<表示
- 就是將十進制的數轉為二進制,將整體向左移動多少位后產生的結果
- 例如:var result = 2 << 5; 2轉為二進制為10,補位后為00000000000000000000000000000010,向左移動5位,得00000000000000000000000001000000,左移會把空位以0進行填充,然后把此結果轉為十進制得64;
- 有符號右移
- 由>>表示
- 例如:var result = 2 >> 5; 2轉為二進制為10,補位后為00000000000000000000000001000000,向左移動5位,得00000000000000000000000000000010,然后把此結果轉為十進制得2;
- 無符號右移
- 由>>>表示
- 會對32位都進行向右移動
- 例如: var result = 2 >> 5; 2轉為二進制為10,補位后為00000000000000000000000001000000,向左移動5位,得00000000000000000000000000000010,然后把此結果轉為十進制得2;但是負數結果就不一樣了,只做了解
- 位操作符應用
- 例如:var str = 'abcd'; var result = ~str.indexOf('a'); // -1 ; var result = ~str.indexOf('e'); // 0