2017年6月22日 星期四

後置遞增減時賦值給自己、不容易發現的無限迴圈、try finally 回傳相反時、快速乘/除 2 的 n 次方

※後置遞增減時賦值給自己

int j=0;
System.out.println(j);
j = j--;
System.out.println(j);
j = j++;
System.out.println(j);
j = j--;
System.out.println(j);
j = j--;
System.out.println(j);

※使用前置遞增/減時,編譯會提示賦值無效,但值是對的
但後置遞增/減並不會,而且永遠都是最後一次給的值,以這個例子,永遠都是 0 「假設第三行 j = j-- 改成 j--,那後面都是 -1」

※正確的寫法是不要用自己去接值,只寫 j++/j-- 即可

※如果真的要接值,要宣告別的變數來接

※在 java 裡原裡如下:
前置遞增
j = j+1;
return j;

後置遞增
int temp = j;
j = j+1;
return temp;

所以問題只會在後置遞增/減時發生
j = j++; 回傳temp值,然後又用自己去接,所以永遠是第一次的值

※java 和 javascript 原理都是這樣;但 C 就不是了


※不容易發現的無限迴圈

int iMax = Integer.MAX_VALUE;
int start = iMax - 10;
int c = 0;
for(int i=start; i<=iMax; i++){
    c++;
}
System.out.println(c);

※一般會寫成 i < iMax,但這裡寫 i <= iMax,所以會多1,但結果並不是 11

※因為 iMax 已經是 Integer 的最大值了,再加1會產生溢位,會變成負的,如此一再的循環,造成無限迴圈

※int i 改 long 可解決



※try finally 回傳相反時

public static void main(String[] args) {
    System.out.println(xxx());
}
    
static boolean xxx() {
    try {
        System.out.println("a");
        // System.exit(0);
        return false;
    } finally {
        System.out.println("b");
        return true;
    }
}

※會印出 a b,並回傳true,編譯完會在 finally 的回傳出現警告「finally block does not complete normally」

※如果將註解打開,只會印 a,System.exit(0) 相當於強制結束


※快速乘/除 2 的 n 次方


// 除 2 的 n 次方
System.out.println(1000 >> 1); // 500
System.out.println(1000 >> 2); // 250
System.out.println(1000 >> 3); // 125
    
// 乘 2 的 n 次方
System.out.println(1000 << 1); // 2000
System.out.println(1000 << 2); // 4000
System.out.println(1000 << 3); // 8000
    
// 只取商
System.out.println(999 >> 1); // 499

※此法不支援小數點

※還有一種「>>>」的很少用,和「>>」差在負數的時候

沒有留言:

張貼留言