java源码阅读笔记(位运算)
2020-06-05 07:39
435 查看
首先从一个题开始
剑指offer求二进制中1的个数
方法1
String s=Integer.toBinaryString(5); int count=0; for(int i=0;i<s.length();i++){ if(s.charAt(i)=='1'){ count++; } }
方法二
return Integer.bitCount(n);
方法三 正经做法
public int NumberOf1(int n) { int count=0; while(n!=0){ count++; n=n&(n-1); } return count; }
解释 首先n-1则相当于最右面的1左面的数全部改变,与操作之后则最右1的所有数归0,对补码也是一样的
举例子5,补码为0101,减一之后是0100,与之后是0100,再-1是0011与之后是0000结束,即每次-1与的操作是将最右1及其之后的0全部清0
顺便来康康Integer类吧
public final class Integer extends Number implements Comparable<Integer>
不可修改,是基类,类型为int(好像是反射?)
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
一些有趣的位运算函数
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); }
传入一个int参数i,返回其二进制最高位1的权值。
因为最大数是32位,所有先最高位左移一位取或,再最高两位左移两位取或,最后最高16位左移16位取或,结果就是全1再减去左移一位的1的就剩下最高位的了
如果是0返回0,如果是负数返回0x8000(int最小值,2^-31-1)
2
public static int lowestOneBit(int i) { // HD, Section 2-1 return i & -i; }
传入一个int参数i,返回其二进制最低位1的权值。,相当于补码的逆运算,变补码是正数按位取反+1
3
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; }
判断前导0个数
每次判断高位有没有非前导0,如果有就加上左移到高位去
但是一共有32个,如果最后左移31位是0则再+1,16,8,4,2,1最后判断最后一位(默认有一个0了已经)
4
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); }
判断末尾几个0,相当于反过来,如果低位没有就减去并二分(实现和上面比好奇怪哦)
5 数有几个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; }
神仙写法,参考https://segmentfault.com/a/1190000015763941,除了666不知道说什么了
6反转
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; }
依然神仙,本质和上一个一样其实是二分查找的过程见https://www.jianshu.com/p/be272c8704d9
7字节反转
public static int reverseBytes(int i) { return ((i >>> 24) ) | ((i >> 8) & 0xFF00) | ((i << 8) & 0xFF0000) | ((i << 24)); }
8符号位
public static int signum(int i) { // HD, Section 2-7 return (i >> 31) | (-i >>> 31); }
这个还是很好懂的,左移或无符号左移看最高位
相关文章推荐
- Java Jdk1.8 HashMap源码阅读笔记二
- Java集合源码阅读笔记-HashSet
- Java框架类源码阅读学习笔记
- java集合源码阅读笔记-HashMap
- Java源码阅读笔记-Integer
- JAVA 集合类(java.util)源码阅读笔记------Vector
- JAVA 集合类(java.util)源码阅读笔记------WeakHashMap
- JDK8源码阅读笔记--------java.lang.Thread
- Java Collection Framework 源码阅读笔记
- [java,spring] spring 源码阅读笔记1
- JAVA 集合类(java.util)源码阅读笔记------ArrayList
- Java Jdk1.8 HashMap源码阅读笔记一
- JAVA 8 treemap 源码阅读笔记
- JAVA 集合类(java.util)源码阅读笔记------Hashtable
- JDK8源码阅读笔记--------java.lang.Object
- JAVA 集合类(java.util)源码阅读笔记------HashMap
- Java集合源码阅读笔记(1)
- java String 源码阅读笔记以及Unicode的学习
- JDK8源码阅读笔记--------java.util.LinkedList
- JDK8源码阅读笔记--------java.util.ArrayList