有意思的按位操做

看到幾個有意思的按位操做的寫法。 java

1.大概改動了下爲了方便理解,參數是int型且大於等於65536,返回這個int型的十位和個位。 學習

public static int getTenAndOne(int value){
        if (value < 0) {
            throw new RuntimeException("無論負數了");
        }
        int q = value / 100;
        int result = value - ((q << 6) + (q << 5) + (q << 2));
        return result;
    }
一般咱們計算一個數的後兩位時,都是用 int result = value%100,但這裏不是這樣玩的。我記得看過一本書講JAVA在%運算符的時候,實際是int result = value-value/100*100。看看上面那個方法裏其實跟這個很像。這麼看來
((q << 6) + (q << 5) + (q << 2))

這個操做其實就是 (a/100)*100的操做,但是移位是怎麼變成*100的呢,曾經的基礎書中這麼講過,向左移移動一位表示*2,因此對上面的表達式進行整理就是 q*2^6+q*2^5+q*2^2=q*(2^6+2^5+2^2)=q*100。呃……。其實當我想明白這個的時候,又一次感嘆,無處不在的數學啊。 google

2.這個是計算出一個小於65536的整數的,個位數是多少。 spa


pulic static int getOne(int value){
	if(value<0||value>=65536){
		throw new RuntimeException("就是無論負數和超限的數");
	}
	int q = (value * 52429) >>> 19;
	int result = value - ((q << 3) + (q << 1));
	return result;
}
根據例1裏面的經驗,能夠很容易看出,其實這個例子就是result=value-value/10*10;


特別是 code


int result = value - ((q << 3) + (q << 1));

很是好理解就是 value-(q*2^3+q*^2)=value-q*(8+2)=value-q*10 ,那麼上面那句話其實就是value/10的意思了,但是簡單的value/10,怎會冒出來乘以52429而後再無符號右移19位呢。我google出來的解釋,也算學習了一下。 get

(i * 52429) >> 19 = i / 10
原理: 52429 / 2 ^19 = 0.10000038146972656 因此(i * 52429) >> 19 = i * 0.1
注意:     2^10=1024, 103/1024=0.1005859375
              2^11=2048, 205/2048=0.10009765625
              2^12=4096, 410/4096=0.10009765625
              2^13=8192, 820/8192=0.10009765625
              2^14=16384, 1639/16384=0.10003662109375
              2^15=32768, 3277/32768=0.100006103515625
              2^16=65536, 6554/65536=0.100006103515625
              2^17=131072, 13108/131072=0.100006103515625
              2^18=262144, 26215/262144=0.10000228881835938
              2^19=524288, 52429/524288=0.10000038146972656 
精度19最高,超過20 * i 就溢出了
而後: (i + (i << 2) + (i << 3) + (i << 6) + (i << 7) + (i << 10) + (i << 11) + (i<<14) + (i<<15)) >> 19 = i / 10

  以上兩個例子是在jedis代碼中看到的,同時在JDK裏的Integer類中的 static void getChars(int i, int index, char[] buf)裏也有。看來jedis做者對JDK源碼有認真閱讀啊。 源碼

3.求一個離一個正整數向上最近的2的次方。 數學

public static int nextPowerOfTwo (int value) {
	if (value == 0) {
		return 1;
	}
	value--;
	value |= value >> 1;
	value |= value >> 2;
	value |= value >> 4;
	value |= value >> 8;
	value |= value >> 16;
	return value + 1;
}
其實求一個整數向上最近的2的次方就是這個整數左數第一個1如下全部位所有變爲1再加1

好比232用二進制表示就是
00000000000000000000000011101000 它的向上最近二進制數就是 io

00000000000000000000000011111111+1 class

依據上面的理論,這個代碼其實就是再逐步的把這個數都變成1,而後再+1

仍是以232爲例子,就不寫成4個字節的形式了

232 = 11101000

1)
1110 1000>>1 //等於0111 0100 就確定把最高1位的下一位變成了1 
1110 1000 | 0111 0100 //等於 1111 1100 就把最高兩位就變成1了

2)
1111 1100>>2 //等於0011 1111 就等於把標紅兩位變成1
1111 1100 | 0011 1111 //等於 1111 1111 至關於把最高四位變成1

3)

1111 1111 >>4 //等於 0000 1111 就等於把標紅四位變成1
1111 1111 | 0000 1111 //等於 1111 1111 至關於把最高位的1個字節變成1

4)其實就把最高的兩個字節變成1

5)把整個int四個字節所有變成1

如上過程,整個int型數的最高的1位如下所有變成了1,最後再加上1 就完成了整個技巧,並返回結果。

相關文章
相關標籤/搜索