java的運算符和strictfp關鍵字

operators也就是運算符,其實和c/c++大同小異,不過也有細微的差別。先介紹最基本的運算符吧;+,-,*,/,%

1、對於除法/,當兩邊的操作數是整數,那麼就是整數除法,否則是浮點數,就是浮點除法floating-point division,最後的%是取餘運算,我們通常叫模運算。這都很熟悉的。

例子;

System.out.println(1 / 0);
打印;Exception in thread "main" java.lang.ArithmeticException: / by zero at coreJava.PrimitiveType.main(PrimitiveType.java:24),出現了除0異常。

System.out.println(1.0 / 0);
打印;Infinity

這是需要注意的地方!浮點運算的除0,不拋出異常,得到一個無窮大的結果。

2、複合運算符;+=等,和c系列一樣,把運算符放到賦值=的緊貼的左邊即可。int x = x + 1;等價於int x += 1;

3、strictfp關鍵字的介紹

對於java的設計目標—在浮點運算中,一次編譯到處運行的可移植性,並且結果不變的實現是很困難的,double類型是64位來存儲一個數值,但是一些處理器處理浮點運算是80位的,比如Intel系列的,在計算的中間步驟,會將80位的結果來計算,到最後的步驟時,截斷爲64位,這樣的話,可以避免指數溢出的問題,並且結果也更加的精確,但是這樣做的結果可能始終和在64位機器上運算的結果不一致,這樣就無法實現移植性,那麼jvm規範就規定,必須把中間的計算結果截斷了!不能等到最後去截斷!雖然可以實現移植性,不過,這樣做的話有可能產生溢出,並且運算速度降低(因爲截斷消耗時間),這也是個矛盾所在,jvm規範也最後承認了這點,那就是完美的性能和結果與理想的移植性的矛盾!最終jvm規範妥協了,規定默認的時候中間運算結果可以不截斷,但是方法或者類,在顯式的使用strictfp關鍵字的時候,必須嚴格的執行浮點運算的計算原理,中間結果必須截斷,來得到可複用移植的結果。用的場合和機會不是很多,一般情況下不用深究。以後在細細的談談浮點數運算的機器表示和實現吧……


自增,自減運算符i++和--;

1、注意它改變的是變量本身的值,故不可以聲明爲常量,比如;1++;這是錯誤的!

2、注意計算順序和前綴後綴的區分,前綴先change,後運算。後綴先運算後change。例如

                int x = 1;
		int y = 1;
		int m = 2 * x++;
		int n = 2 * ++y;
		System.out.println("m = " + m + " " + "n = " + n + " " + "x = " + x
				+ " " + "y = " + y);

打印;m = 2 n = 4 x = 2 y = 2

3、強烈建議自增減類運算符單獨寫在表達式外邊,不要寫在表達式的內部,那樣的話,整個程序內寫多了會看着心煩,產生混淆和bug變得多多!


關係運算符和boolean運算符;判等==,不等!=,小於<,大於>,小於等於<=,大於等於>=,邏輯與&&,邏輯或||,邏輯非!,非~,或|,與&,異或^,三元?:,左移《,帶符號右移》,無符號右移>>>

1、需要注意短路操作,邏輯運算符;&&和||,均是隻看第一個表達式即可,前者是一假則假,後者是一真則真。舉例;

		int x = 11;
		if (x != 0 && x > 10) {
			System.out.println("ok");
		}

打印;ok

但是當左邊變爲x==0,那就假了。

		if (x == 0 && x > 10) {
			System.out.println("true");
		}else {
			System.out.println("false");
		}
打印;false

2、對於三元運算符,用的不是很多,用來比較兩個表達式而做出選擇。例如;

		int x = 11;
		int y = 10;
		System.out.println(x > y ? x : y);
打印;11

3、移位運算符;與&,或|,^異或,非!,若他們在位模式下工作,通過這些運算符可以實現屏蔽數位的職責。當然也可以進行邏輯判斷,&和|如果用在布爾運算中,和1中雙與,雙或類似,只是沒有短路操作,必須兩個表達式都判斷真假,結果也是布爾的。在二進制的位模式下遵循法則;&一假則假,|一真則真,^相同則假,原理是通過使用2的冪次方來起到屏蔽的作用,只剩下某個想要的位。如例子;

		int x = 11;//二進制是1011
		//注意這些運算符是在位模式下運算的,括號裏啓到屏蔽作用,8的二進制是1000,
		int result = (x & 8) / 8;//後三位屏蔽了,8除以8最後得到1
		System.out.println(result);

再看一例;

                int a = 1;
		int b =2;
		if (a < 0 && b < a--) {
			System.out.println("ok");
		}
		System.out.println(a);
打印a的值是1,短路了。

		int a = 1;
		int b = 2;
		if (a < 0 & b < a--) {
			System.out.println("ok");
		}
		System.out.println(a);
打印a的值是0,說明兩個表達式都執行了!!!記住區別。
4、特別注意邏輯移位和算數移位;》右移,《左移,符號的左邊是操作數,右邊是參數。對於帶符號右移》符號,如果是正數,則高位補0,負數則符號位不變,左邊補上符號位1(因爲0正1負)。對於帶符號左移《,則是低位直接補充0即可,很簡單。他們在位模式下進行數位的屏蔽作用。且《左移一位等價於乘2一次,對於2的冪次整數,》右移一位等價於除2一次。

		// 打印4,乘2
		System.out.println(2 << 1);
		// 打印1
		System.out.println(2 >> 1);
		// 打印-4
		System.out.println(-2 << 1);
		// 打印-1
		System.out.println(-2 >> 1);
		// 打印-6
		System.out.println(-3 << 1);
		// 這裏說右移一次就是除一次2是錯誤的,前提是2的冪次數
		// 打印2
		System.out.println(5 >> 1);
		// 打印-2
		System.out.println(-3 >> 1);

要知道java中的int是32位,正數以原碼的形式存儲,負數以補碼的形式存儲。且負數的補碼等於原碼的反碼加1,而正數的原碼補碼反碼同一

5、>>>無符號右移運算符,高位補充0即可,帶符號》右移運算符用符號位填充高位!且沒有<<<。

		// 打印2147483647
		System.out.println(-2 >>> 1);
		// 打印1,無符號就是正數
		System.out.println(2 >>> 1);

java是沒有無符號數的,也就是說java都是有符號的參與運算!都適用!c++要區分有符號和無符號。無符號右移,不論正負,高位始終補充0,地位捨棄!當我們要作位移的原始值並非代表數值時(例如:表示顏色圖素的值),可能就會需要使用此種無符號的位移。

6、對於符號右邊的參數,時刻注意;int型需要先模32,long型需要先模64。比如1《35和1《3等價,因爲35模32是3,他們都等價左移3位,1的二進制模式下左移三位就等於8。例如;

		System.out.println(1 << 3);
		// 打印8
		System.out.println(1 << 35);
		//打印8
		System.out.println(1L << 3);
		//打印34359738368
		System.out.println(1l << 35);
		//打印1
		System.out.println(1l << 64);
		//打印2
		System.out.println(1l << 65);

注意;後幾個都是long型。

7、按位取反~運算符

System.out.println(~1);

打印;-2

1默認32位int型,是正數,0000 0000 0000 0000 0000 0000 0000 0001,進行按位取反運算之後得到 1111 1111 1111 1111 1111 1111 1111 1110,結果變爲了負數,負數是按照補碼存儲,即這個數是特麼的補碼!!!!那麼按照原碼的反碼(符號位不變)再加上1爲補碼的逆運算得出;1000 0000 0000 0000 0000 0000 0000 0010,就是-2,即原數加1,再取負!


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