天天看點

java 解惑

1.奇偶性

public static boolean isOdd(int i){

return i%2==1;

}

這個程式并不一定獲得正确答案,因為i有可能是負數。

健壯的寫法是這樣;

return i%2!=0;

或者這樣:

return (i&1)!=0;

2.找零

System.out.println(2.0-1.10);

它不會列印出0.9,更不會列印出0.90.列印出的是0.8999999999999999。

因為1.1這個數字不能精确的表示成為一個double,它被表示成最接近它的double值。

java有兩個辦法來解決這個問題。一個是用int

System.out.println(200-110);

一個是用java.math.BigDecimal

System.out.println(new BigDecimal("2.0")-new BigDecimal("1.10"));

總之,在需要精确答案的地方,要避免使用float和double

3.長整除

這是一個關于兩個long型值的整除。

被除數是一天裡的微妙數,除數是一天裡的毫秒數

public static void devide(){
		final long MICROS_PER_DAY=24*60*60*1000*1000;
		final long MILLIS_PER_DAY=24*60*60*1000;
		System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
	}
           

結果應該是1000才對。但是不是。

問題出在了MICROS_PER_DAY的計算溢出了。盡管計算的結果适合放在long中,但是并不适合放在int中。

在計算過程中始終是以int運算執行的,隻有在運算完成之後,結果才被提升到long,但是已經溢出。

最後傳回的是小了200倍的數。從int提升到double是拓寬的類型轉換。

為什麼會這樣呢?因為計算一直都是按int運算的,并且java不具有目标确定類型的特性。這是一種語言性質

指計算所使用的類型不會受存儲結果的變量的類型影響。那是不是應該影響影響呢?各有各的看法。

正确的寫法:

public static void devide(){
		final long MICROS_PER_DAY=24L*60*60*1000*1000;
		final long MILLIS_PER_DAY=24L*60*60*1000;
		System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
	}
           

從開始我們就用Long型計算。

當在操作很大的數字的時候,千萬要提防溢出,這是一個緘默的殺手。。。

java之父在《java 解惑》中是這麼說的:

語言設計者從中可以吸取的教訓是:也許降低緘默溢出産生的可能性确實是值得做的一件事。

這可以通過對不會産生緘默溢出的運算提供支援來實作。程式可以抛出一個異常而不是直接溢出,就像 Ada 所作的那樣,

或者它們可以在需要的時候自動地切換到一個更大的内部表示上以防止溢出,就像 Lisp 所作的那樣。

這兩種方式都可能會遭受與其相關的性能方面的損失。降低緘默溢出的另一種方式是支援目标确定類型,但是這麼做會顯著地增加類型系統的複雜度