JAVA基本類型及位運算

原碼、反碼和補碼

原碼,反碼,補碼的產生過程,就是爲了解決,計算機做減法和引入符號位(正號和負號)的問題。

原碼

*原碼:*是最簡單的機器數表示法。用最高位表示符號位,‘1’表示負號,‘0’表示正號。其他位存放該數的二進制的絕對值。

反碼

反碼:正數的反碼還是等於原碼;負數的反碼就是他的原碼除符號位外,按位取反。

補碼

補碼:正數的補碼等於他的原碼 負數的補碼等於反碼+1。 (這只是一種算補碼的方式)

移碼

移碼(又叫增碼)是符號位取反的補碼,一般用指數的移碼減去1來做浮點數階碼,引入的目的是爲了保證浮點數的機器零爲全0。

計算機加減流程及原理

計算機只有加法器 -> 正數和負數的加減運算 ->轉化爲補碼進行加法運算 ->補碼運算的原理在於取負數的同餘數進行加法運算

補碼運算規則

[原碼] + [原碼] -> [補碼]+[補碼] = [補碼] -> [原碼](結果)

位運算核心知識點

  • 位運算操作的是整數
  • 計算機中,整數以機器數補碼的形式存儲
  • 位運算操作的是整數的二進制補碼

位運算

  • 位運算只可以處理整數類型(byte、short、int、long)

  • 位運算操作的是整數的二進制補碼

  • 位運算對byte和short進行移位操作時,在移位之前,會被轉換成int類型,得到的結果也是int類型

位運算規則

位運算符 說明
&
|
^ 異或
按位取反
<< 左移運算符,符號位不變,右側低位補0,左側高位捨棄。向左移動指定位數,一般情況下每移動一位都會乘以2(除符號位之外,最高位不爲1的情況下,高位爲1時,超過了位數限制)
>> 右移運算符,符號位不變,右側低位捨棄,左側高位正數補0,負數補1。向右移動指定位數,一般情況下每移動一位都是除以2(低位爲1時,會丟失精度)
>>> 按位右移補零操作符,無論正負,右側低位捨棄,左側高位插入0

位運算符操作的都是補碼,尤其是負數移位操作,應該深刻認識操作的是負數的二進制補碼!!!

JAVA基本類型的默認值和取值範圍

默認值 存儲需求(字節) 取值範圍 示例
byte 0 1 -27—27-1 byte b=10;
short 0 2 -215—215-1 short s=10;
int 0 4 -231—231-1 int i=10;
long 0 8 -263—263-1 long o=10L;
float 0.0f 4 IEEE754 float f=10.0F
double 0.0d 8 IEEE754 double d=10.0;
boolean false 1 true\false boolean flag=true;
char ‘ \u0000′ 2 0—2^16-1 char c=’c’ ;

int類型和byte數組的相互轉化

/** 
 * int到byte[] 
 * @param i 
 * @return 
 */  
public static byte[] intToByteArray(int i) {  
    byte[] result = new byte[4];  
    // 由高位到低位  
    result[0] = (byte) ((i >> 24) & 0xFF);  
    result[1] = (byte) ((i >> 16) & 0xFF);  
    result[2] = (byte) ((i >> 8) & 0xFF);  
    result[3] = (byte) (i & 0xFF);  
    return result;  
}  
  
/** 
 * byte[]轉int 
 * @param bytes 
 * @return 
 */  
public static int byteArrayToInt(byte[] bytes) {  
    int value = 0;  
    // 由高位到低位  
    for (int i = 0; i < 4; i++) {  
        int shift = (4 - 1 - i) * 8;  
        value += (bytes[i] & 0x000000FF) << shift;// 往高位遊  
    }  
    return value;  
}  
  
public static void main(String[] args) {  
    byte[] b = intToByteArray(128);  
    System.out.println(Arrays.toString(b));  
      
    int i = byteArrayToInt(b);  
    System.out.println(i);  
}

位運算代碼

	public static void testBitOperation() {
		//數值在機器中以補碼的形式存儲,位運算規則操作的是數值的二進制補碼
		int positive = 2;  //0... 0000 0010(原碼) 0... 0000 0010(反碼)  0... 0000 0010(補碼)
		int negative = -2; //1... 0000 0010(原碼) 1... 1111 1101(反碼)  1... 1111 1110(補碼)
	       
		System.out.println("positive:" + positive);
		System.out.println("negative:" + negative);
		System.out.println("&:" + (positive & negative));//0... 0000 0010(補碼)  0... 0000 0010(反碼)  0... 0000 0010(原碼) 
		System.out.println("|:" + (positive | negative));//1... 1111 1110(補碼)  1... 1111 1101(反碼)  1... 0000 0010(原碼)
		System.out.println("~positive:" + ~positive);//1... 1111 1101(補碼) 1... 1111 1100(反碼)  1... 0000 0011(原碼)
		System.out.println("~negative:" + ~negative);//0... 0000 0001(補碼) 0... 0000 0001(反碼)  0... 0000 0001(原碼)   
		System.out.println("^:" + (positive ^ negative));//1... 1111 1100(補碼)  1... 1111 1011(反碼)  1... 0000 0100(原碼)
		
		System.out.println("positive << 3:" + (positive << 3));//0... 0001 0000(補碼) 0... 0001 0000(反碼) 0... 0001 0000(原碼)
		System.out.println("negative << 3:" + (negative << 3));//1... 1111 0000(補碼) 1... 1110 1111(反碼) 1... 0001 0000(原碼)
		
		System.out.println("positive >> 3:" + (positive >> 3));//0... 0000 0000(補碼) 0... 0000 0000(反碼) 0... 0000 0000(原碼)
		System.out.println("negative >> 3:" + (negative >> 3));//1... 1111 1111(補碼) 1... 1111 1110(反碼) 1... 0000 0001(原碼)
		
		
		System.out.println("positive >>> 3:" + (positive >>> 3));//0... 0000 0000(補碼) 0... 0000 0000(反碼) 0... 0000 0000(原碼)
		System.out.println("negative >>> 3:" + (negative >>> 3));//0001 1111 1111 1111 1111 1111 1111 1111(補碼\反碼\原碼) 
		System.out.println("negative >>> 3:" + Integer.parseInt("00011111111111111111111111111111", 2));
	}


/**output**/
positive:2
negative:-2
&:2
|:-2
~positive:-3
~negative:1
^:-4
positive << 3:16
negative << 3:-16
positive >> 3:0
negative >> 3:-1
positive >>> 3:0
negative >>> 3:536870911
negative >>> 3:536870911

float類型和double類型

符號位 階碼 尾數 長度
float 1 8 23 32
double 1 11 52 64

float和double計算方式

float和double取值範圍和精度問題

  • float和double的取值範圍是由指數的位數來決定的

  • float的指數範圍爲-27~27-1(即-128127),而double的指數範圍爲-2^102^10-1(即-1024~1023)

  • float的範圍爲-2^128 ~ +2^128(-3.40E+38 ~ +3.40E+38)

  • double的範圍爲-2^1024 ~ +2^1024(-1.79E+308 ~ +1.79E+308)

  • float和double的精度是由尾數的位數來決定的

  • float:2^23 = 8388608,一共七位,這意味着最多能有7位有效數字,即float的精度爲6~7位有效數字;

  • double:2^52 = 4503599627370496,一共16位,同理,double的精度爲15~16位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章