国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Integer位操作技巧解析

2019-11-08 02:34:57
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

整數(shù)二進(jìn)制左邊1最早出現(xiàn)的位置

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); }

畫個(gè)圖簡(jiǎn)單說(shuō)明一下算原理,下圖以8為為例,做了左移1,2,4位之后的效果,最終的效果就是在最早出現(xiàn)1的位置后面都是1。 32位的int也是類似的,最終的效果就是從左邊第一位是1開始后面都是1。 這里寫圖片描述

整數(shù)二進(jìn)制右邊1最早出現(xiàn)的位置

public static int lowestOneBit(int i) { // HD, Section 2-1 return i & -i; }

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

整數(shù)二進(jìn)制左邊開頭有連續(xù)多少個(gè)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; }

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

整數(shù)二進(jìn)制右邊結(jié)束有連續(xù)多少個(gè)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); }

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

整數(shù)二進(jìn)制總共有多少個(gè)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; }

這個(gè)算法也是神乎其技,它的做法是分別計(jì)算每2位,每4位,每8位,每16位,每32位..這樣的順序計(jì)算.以第一行為例,每2位有4種情況,分別是00,01,10,11, 計(jì)算i-((i>>>1) & 01) 可以得到00,01,01,10, 就表示1的個(gè)數(shù)。

整數(shù)向左滾動(dòng)X位

public static int rotateLeft(int i, int distance) { return (i << distance) | (i >>> -distance); }

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

整數(shù)向右滾動(dòng)X位

public static int rotateRight(int i, int distance) { return (i >>> distance) | (i << -distance); }

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

整數(shù)二進(jìn)制反轉(zhuǎn)

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; }

以第一行為例,它的作用就是兩兩交換,可以通過(guò)下圖分析可得。 這里寫圖片描述 同理,第二行是每2位交換,第三行是每4位交換,假設(shè)原來(lái)是b1b2b3b4b5b6b7b8,那么三行執(zhí)行后,結(jié)果就是b8b7b6b5b4b3b2b1,就是一個(gè)字節(jié)的位進(jìn)行反轉(zhuǎn)了。最后一句就是按字節(jié)反轉(zhuǎn)一下,最終結(jié)果就是按位反轉(zhuǎn)了。

整數(shù)的符號(hào),0返回0,正數(shù)返回1,負(fù)數(shù)返回-1

public static int signum(int i) { // HD, Section 2-7 return (i >> 31) | (-i >>> 31); }

感覺這個(gè)實(shí)現(xiàn)有點(diǎn)多此一舉,直接大小判斷很簡(jiǎn)單,也很直觀,為什么不采用?

還是畫個(gè)圖說(shuō)明一下吧。 這里寫圖片描述

整數(shù)按字節(jié)反轉(zhuǎn)

public static int reverseBytes(int i) { return ((i >>> 24) ) | ((i >> 8) & 0xFF00) | ((i << 8) & 0xFF0000) | ((i << 24)); }

這個(gè)算法很好理解,第一個(gè)字節(jié)右移24位就跑到第四個(gè)字節(jié)去了,第二個(gè)字節(jié)右移8位到了第三位,和FF00與運(yùn)算就抹掉對(duì)第四個(gè)字節(jié)的影響。后面的就不解釋了。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 敦化市| 兴海县| 连平县| 竹溪县| 汝阳县| 临泉县| 杭锦后旗| 梁河县| 宜兰市| 定西市| 阿巴嘎旗| 涞源县| 阿图什市| 视频| 武鸣县| 永泰县| 邻水| 乌海市| 天等县| 巴青县| 永清县| 洛宁县| 鄱阳县| 且末县| 杭锦后旗| 富川| 徐闻县| 新宁县| 连江县| 合水县| 马鞍山市| 宁陕县| 兰考县| 灌云县| 惠州市| 正定县| 灯塔市| 淮安市| 车致| 宁武县| 武安市|