計算機和真實生活中不同汗菜,一個數(shù)在計算機中只能以二進制(0或者1)的方式表示添诉,現(xiàn)實生活中主要以十進制表示梢褐,在二進制的標示中旺遮,最高位是符號位,最高位如果為0 盈咳,則表示該數(shù)的十進制表示為正數(shù)耿眉,如果最高位為1,則該數(shù)位負數(shù)鱼响。以十進制3為例鸣剪,改為8位的二進制,則是[0000 0011],如果是-3轉(zhuǎn)換為8位的二進制是[1000 0011].在這里[0000 0011] 與3表示的意思相同 ,不過[0000 0011] 是機器數(shù)丈积,3為真值筐骇。
原碼, 反碼, 補碼的基礎(chǔ)概念
1. 原碼
原碼:是最簡單的機器數(shù)表示法。用最高位表示符號位桶癣,‘1’表示負號拥褂,‘0’表示正號。其他位存放該數(shù)的二進制的絕對值牙寞。
若以1000? 0010 為例子
最高位為‘1’,表示這是一個負數(shù)饺鹃,其他七位為‘000? 0010’
即(0*2^7)+(0*2^6)+(0*2^5)+(0*2^4)+(0*2^3)+(0*2^2)+(1*2^1)+(0*2^0)=2(‘^’表示冪運算符)
所以1000? 0010 是-2
2.反碼
反碼:正數(shù)的反碼還是等于原碼
負數(shù)的反碼就是他的原碼除符號位外莫秆,按位取反
若以帶符號位的八位二進制數(shù)為例:
3是正數(shù),反碼與原碼相同悔详,則可以表示為0000 0011
-3的原碼是1000 0011镊屎,符號位保持不變,低七位(000 0011)按位取反得(100? 1100)
3.補碼
補碼:正數(shù)的補碼等于他的原碼
負數(shù)的補碼等于反碼+1茄螃。
(這只是一種算補碼的方式缝驳,多數(shù)書對于補碼就是這句話)
前言
日常開發(fā)中位運算不是很常用,但是巧妙的使用位運算可以大量減少運行開銷归苍,優(yōu)化算法用狱。舉個例子,翻轉(zhuǎn)操作比較常見拼弃,比如初始值為1夏伊,操作一次變?yōu)?,再操作一次變?yōu)?吻氧∧缬牵可能的做法是使用三木運算符,判斷原始值為1還是0盯孙,如果是1鲁森,設(shè)置為0,否則設(shè)置為0.但是使用位運算振惰,不用判斷原始值歌溉,直接改變值就可以。當然骑晶,一條語句可能對代碼沒什么影響研底,但是在高重復,大數(shù)據(jù)量的情況下將會節(jié)省很多開銷透罢。
位運算符
一些只需要一個操作數(shù)的運算符稱為一元運算符(或單目運算符)。
二元運算是由兩個元素形成第三個元素的一種規(guī)則冠蒋。例如數(shù)的加法及乘法;更一般地,由兩個集合形成第三個集合的產(chǎn)生方法或構(gòu)成規(guī)則稱為二次運算羽圃。(或雙目運算符)
位邏輯運算符
位邏輯運算符包含 4 個:&(與)、|(或)抖剿、~(非)和 ^(異或)朽寞。除了 ~(即位取反)為單目運算符外,其余都為雙目運算符斩郎。表 1 中列出了它們的基本用法脑融。
位與運算符
位與運算符為&,其運算規(guī)則是:參與運算的數(shù)字缩宜,低位對齊肘迎,高位不足的補零甥温,如果對應(yīng)的二進制位同時為 1,那么計算結(jié)果才為 1妓布,否則為 0姻蚓。因此,任何數(shù)與 0 進行按位與運算匣沼,其結(jié)果都為 0狰挡。
例如下面的表達式:100&0
0110 0100? ---> 100
&0000 0000 --->? 0
? 0000 0000 --->? 0
代碼實現(xiàn):
? ? ? int x = 100,y = 0;
? ? ? int z = x&y;
? ? ? System.out.println("運算結(jié)果:"+z);
//運算結(jié)果:0
位或運算符
位或運算符為|,其運算規(guī)則是:參與運算的數(shù)字释涛,低位對齊加叁,高位不足的補零。如果對應(yīng)的二進制位只要有一個為 1唇撬,那么結(jié)果就為 1它匕;如果對應(yīng)的二進制位都為 0,結(jié)果才為 0局荚。
下面是一個使用位或運算符的表達式:4|7
0000 0100--->4
|? ? 0000 0111--->7
? ? 0000 0111--->7
代碼驗證:
? int x = 4,y = 7;
? ? ? int z = x|y;
? ? ? System.out.println("運算結(jié)果:"+z);
//運算結(jié)果:7
位異或運算符
位異或運算符為^超凳,其運算規(guī)則是:參與運算的數(shù)字,低位對齊耀态,高位不足的補零轮傍,如果對應(yīng)的二進制位相同(同時為 0 或同時為 1)時,結(jié)果為 0首装;如果對應(yīng)的二進制位不相同创夜,結(jié)果則為 1
下面是一個使用位異或運算符的表達式:4^7
0000 0100--->4
^? 0000 0111--->7
? ? 0000 0011--->3
代碼驗證:
? ? ? int x = 4,y = 7;
? ? ? int z = x^y;
? ? ? System.out.println("運算結(jié)果:"+z);
//運算結(jié)果:3
位取反運算符
位取反運算符為~,其運算規(guī)則是:只對一個操作數(shù)進行運算仙逻,將操作數(shù)二進制中的 1 改為 0驰吓,0 改為 1。
下面是一個使用位取反運算符的表達式: ~5
位移運算符
位移運算符用來將操作數(shù)向某個方向(向左或者右)移動指定的二進制位數(shù)系奉。表 2 列出了 Java 語言中的兩個位移運算符檬贰,它們都屬于雙目運算符。
左位移運算符
左移位運算符為?缺亮,其運算規(guī)則是:按二進制形式把所有的數(shù)字向左移動對應(yīng)的位數(shù)翁涤,高位移出(舍棄),低位的空位補零萌踱。
例如葵礼,將整數(shù) 7向左位移 1 位的過程如下:
? ? ? ? ? ? ? ? 0000 0111
? ? ? ? ? ? ? ? 00000 1110---->14
原來數(shù)的所有二進制位都向左移動 1 位。原來位于左邊的最高位 0 被移出舍棄并鸵,再向尾部追加 0 補位鸳粉。最終到的結(jié)果是14,相當于原來數(shù)的 2 倍园担。
代碼驗證:
? ? ? int x = 7;
? ? ? int z = x <<1;
? ? ? System.out.println("運算結(jié)果:"+z);
? ? ? //運算結(jié)果:14
右位移運算符
右位移運算符為?届谈,其運算規(guī)則是:按二進制形式把所有的數(shù)字向右移動對應(yīng)的位數(shù)枯夜,低位移出(舍棄),高位的空位補零疼约。
例如卤档,將整數(shù) 7向右位移 1 位的過程如下:
? ? ? ? ? ? ? ? ? ? ? ? 0000 0111
0000 00111---->3
原來數(shù)的所有二進制位都向右移動 1 位。原來位于右邊的最低位 1 被移出舍棄程剥,再向最高位追加 0 補位劝枣。最終到的結(jié)果是 3,相當于原數(shù)整除 2 余數(shù)舍棄的結(jié)果织鲸。
復合位賦值運算符
所有的二進制位運算符都有一種將賦值與位運算組合在一起的簡寫形式舔腾。復合位賦值運算符由賦值運算符與位邏輯運算符和位移運算符組合而成。表 3 列出了組合后的復合位賦值運算符搂擦。
? int a = 1;
? ? ? int b = 2;
? ? ? int c = 3;
? ? ? a &= 4;
? ? ? a |= 4;
? ? ? a ^= c;
? ? ? a -= 6;
? ? ? b >>= 1;
? ? ? c <<= 1;
? ? ? System.out.println("a = " + a);
? ? ? System.out.println("b = " + b);
? ? ? System.out.println("c = " + c);
????????a = 1
????????b = 1
????????c = 6