日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 0x3f_Java源码位操作技巧欣赏

發布時間:2023/12/19 java 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 0x3f_Java源码位操作技巧欣赏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近有人問些邏輯位移,算術位移的區別和應用場景,翻了一些舊材料,重新整理一下發出來,給大家欣賞一下java源碼中涉及的位操作技巧,摘取的是Integer的源碼實現。

整數二進制左邊1最早出現的位置

public static int highestOneBit(int i) {

// HD, Figure 3-1

i |= (i >> 1);

i |= (i >> 2);

i |= (i >> 4);

i |= (i >> 8);

i |= (i >> 16);

return i - (i >>> 1);

}

畫個圖簡單說明一下計算的原理,簡化一下只用8位為例,做了右移1,2,4位之后的效果,最終的效果就是在最早出現1的位置后面都是1。 32位的int也是類似的,最終的效果就是從左邊第一位是1開始后面都是1。

有點神奇,仔細想想,前面的多次移位就是最前面那個1填滿后面所有位(無論后面是0還是1)。

整數二進制右邊1最早出現的位置

public static int lowestOneBit(int i) {

// HD, Section 2-1

return i & -i;

}

負數以補碼形式存在,一個負數的補碼,就是對應整數的二進制再取反加一。i和-i總有一個是正數,假設是i吧,由于兩個數相加是0,在二進制角度來看,假設i最右邊出現1的位置是k,那么在相同位置上-i必定也是1,并且-i在k以后的位也是0,這2位相加是0,并且進位1,那么要是k-1位相加得到0,兩個數字在k-1位上只能是一個1,另外一個是0,以此類推,可以得到從左邊第一位開始直到k-1位都是不同的。兩個數進行與運算,只會在k位保留1,其他位都變成0。

整數二進制左邊開頭有連續多少個0

public static int numberOfLeadingZeros(int i) {

// HD, Figure 5-6

if (i == 0)

return 32;

int n = 1;

if (i >>> 16 == 0) { n += 16; i <<= 16; }

if (i >>> 24 == 0) { n += 8; i <<= 8; }

if (i >>> 28 == 0) { n += 4; i <<= 4; }

if (i >>> 30 == 0) { n += 2; i <<= 2; }

n -= i >>> 31;

return n;

}

以移動16位為例子,如果左移16位之后是0,那么前16位都是0,那么就只要判斷后面16位就可以了。 如果不是0,那么只要判斷前面16位就可以了,和前面的區別就是,它不需要移位。后面的移位操作,以此類推就可以了。

整數二進制右邊結束有連續多少個0

public static int numberOfTrailingZeros(int i) {

// HD, Figure 5-14

int y;

if (i == 0) return 32;

int n = 31;

y = i <<16; if (y != 0) { n = n -16; i = y; }

y = i << 8; if (y != 0) { n = n - 8; i = y; }

y = i << 4; if (y != 0) { n = n - 4; i = y; }

y = i << 2; if (y != 0) { n = n - 2; i = y; }

return n - ((i << 1) >>> 31);

}

和上面的差不多,假設右移16位不等于0,那么說明只需要判斷右邊16位就可以了。如果等于0,那說明要判斷左邊16位。后面的移位操作,以此類推就可以了。

整數二進制總共有多少個1

public static int bitCount(int i) {

// HD, Figure 5-2

i = i - ((i >>> 1) & 0x55555555);

i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);

i = (i + (i >>> 4)) & 0x0f0f0f0f;

i = i + (i >>> 8);

i = i + (i >>> 16);

return i & 0x3f;

}

這個算法我是看呆了,神乎其技,它的做法是分別計算每2位,每4位,每8位,每16位,每32位..這樣的順序計算。

以第一行為例,0x55555555剛好每2位是01,而每2位有4種情況,分別是00,01,10,11, 計算i-((i>>>1) & 01) 可以得到00,01,01,10, 就對應表示1的個數。是不是很神奇。

整數向左滾動X位

public static int rotateLeft(int i, int distance) {

return (i << distance) | (i >>> -distance);

}

這是基本的移位操作,注意的是右邊要采用算術右移。

整數向右滾動X位

public static int rotateRight(int i, int distance) {

return (i >>> distance) | (i << -distance);

}

和上面的一樣,就不再詳述了。

整數二進制反轉

public static int reverse(int i) {

// HD, Figure 7-1

i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;

i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;

i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;

i = (i << 24) | ((i & 0xff00) << 8) |

((i >>> 8) & 0xff00) | (i >>> 24);

return i;

}

這個代碼也很神奇,完全看不懂。以第一行為例,它的作用就是兩兩交換,可以通過下圖分析可得。

同理,第二行是每2位交換,第三行是每4位交換,假設原來是b1b2b3b4b5b6b7b8,那么三行執行后,結果就是b8b7b6b5b4b3b2b1,就是一個字節的位進行反轉了。最后一句就是按字節反轉一下,最終結果就是按位反轉了。

整數的符號,0返回0,正數返回1,負數返回-1

public static int signum(int i) {

// HD, Section 2-7

return (i >> 31) | (-i >>> 31);

}

感覺這個實現有點多此一舉,直接大小判斷很簡單,也很直觀,為什么不采用?

還是畫個圖說明一下吧。

整數按字節反轉

public static int reverseBytes(int i) {

return ((i >>> 24) ) |

((i >> 8) & 0xFF00) |

((i << 8) & 0xFF0000) |

((i << 24));

}

這個算法很好理解,第一個字節右移24位就跑到第四個字節去了,第二個字節右移8位到了第三位,和FF00與運算就抹掉對第四個字節的影響。后面的就不解釋了。

從Integer的方法實現看,有些位操作的技巧實在很巧妙,能想出來真的不容易。像java之類的源代碼還是有很多有趣,實用的技巧的,有機會再分享一些。

總結

以上是生活随笔為你收集整理的java 0x3f_Java源码位操作技巧欣赏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。