複習筆記5 位運算符 以及位移超出整數類型邊界的回滾原理

public class Test6
{
	public static void main(String[] args)
	{
		//位運算符
		// << 左移運算符
		//5 的二進制是 0000 0101
		//左移一位的話0000 1010
		//5 左移一位是10,是不是相當於5*2
		System.out.println(5 << 1);
		//3左移一位正好是6
		System.out.println(3 << 1);
		//3左移兩位是12,也就是*4
		System.out.println(3 << 2);
		//對比下,其實這個表達式跟上方的位移的結果
		//是一致的,運算效率上卻要慢很多,這裏只是
		//描述下,左移相當於乘上2的幾次冪
		System.out.println((int)(3 * Math.pow(2, 2)));
		//下邊發現左移0和32還是5,爲什麼呢?
		System.out.println(5 << 0);
		System.out.println(5 << 32);
		//木哈哈,這個絕對大殺器,爲什麼-1是31,-2是30?
		System.out.println(5 << -1);
		System.out.println("====================================>");
		
		//打印一下x的位移情況,發現左移32位,x還是
		//原值,爲什麼會這樣?
		//分析下最後幾行,發現,並不是逐位補位的,
		//最後一行的像突然插進去的一樣。
		int x = 7;
		for (int shift = 0; shift <= 32; shift++)
        {
	        System.out.println(getIntegerToBinary(x << shift));
        }
		System.out.println("====================================>");
		//到這裏可以看見,貌似從32開始,又開始像0-31
		//那樣子逐位位移了,到第64次的時候又會在繼續
		//這看起來是不是像模運算呢?
		//其實這不難理解,比如沒有這個現象的話,咱就單
		//說位移,32位之後就都是0了吧,顯然沒有意義,
		//對於一個int的有效位移次數僅是0-31
		System.out.println(getIntegerToBinary(x << 33));
		System.out.println("====================================>");
		//事實證明,猜想是對的,但問題是,真的是這樣?
		//模運算是很慢的,如果真是這樣,位移操作還能比
		//乘法快?
		for (int shift = 0; shift <= 32; shift++)
        {
	        System.out.println(getIntegerToBinary(x << shift % 32));
        }
		System.out.println("====================================>");
		//既然有效位移次數是0-31,那麼31的2進制是什麼?
		//是11111五個一,咱是不是只需要拿到位移次數的
		//低五位就可以了?你可以打印下0-64的2進制,看看
		//後5位是什麼情況
		//如果這個實在難以理解,你就當成是32進制,每次取
		//這個數的32進制的個位數
		for (int shift = 0, mask = 0x0000001f; shift <= 32; shift++)
        {
	        System.out.println(getIntegerToBinary(x << (shift & mask)));
        }
		System.out.println("====================================>");
		//這個眼熟不?如果 % 的方式是對的?左移-1位你怎麼
		//解釋?當然你理解成0相當於32,-1相當於31這是可以
		//但是,你怎麼解釋-1和31的關係?有什麼證據?
		//總不能說-1%32是31,那還不讓人笑掉大牙?
		//-1 & 0x0000001f是多少?取後五位正好是31
		System.out.println(getIntegerToBinary(x << (-1 % 32)));
		System.out.println(getIntegerToBinary(x << (-1 & 0x0000001f)));
		//將上邊的兩行化簡,最後就是這樣的了,結果一樣,那
		//也就是說-1被處理,跟%沒有一毛錢關係,問題發生在
		//-1怎麼變成31,呵呵,已經很明顯了吧?
		System.out.println(getIntegerToBinary(x << -1));
		System.out.println(getIntegerToBinary(x << 31));
		System.out.println("====================================>");

		//這個足夠看出來3種位移方式的區別了
		//至於?的運算符,+ ^ |三種都行
		//就是個孔雀開屏而已
		for (int shift = 1; shift < Integer.SIZE; shift++)
        {
			System.out.print(getIntegerToBinary(-1 << shift));
			System.out.print(" ? " + getIntegerToBinary(-1 >>> Integer.SIZE - shift));
			System.out.println(" = " +getIntegerToBinary(-1 >> shift));
	        
        }
		System.out.println("====================================>");
		//上邊的另外一種實現方式
		int a = -1;
		for (int i =1;i<32; i++)
		{        
            a=a<<1;
            System.out.println(getIntegerToBinary(a)+" ^ "
                                   +getIntegerToBinary(~a)+" = "
                                   +getIntegerToBinary(a+~a));
		}        
		System.out.println("====================================>");

	}
	
	public static final String DEFAULT_INT_ZERO = "00000000000000000000000000000000";
	public static final String getIntegerToBinary(int value)
	{
		String binary = Integer.toBinaryString(value);
		int length = Integer.SIZE - binary.length();
		return DEFAULT_INT_ZERO.substring(0, length) + binary;
	}

}

發佈了49 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章