• Java Integer类分析


      public static final int   MIN_VALUE = 0x80000000;  -2^31

     public static final int   MAX_VALUE = 0x7fffffff; 2^31-1

     public static String toString(int i, int radix)

    该方法返回一个字符串形式的参数,第二个参数为指令的基数,将第一个参数转换为以第二个参数为基数的字符串

    package com.yiibai;
    
    import java.lang.*;
    
    public class IntegerDemo {
    
       public static void main(String[] args) {
    
         Integer i = new Integer(10);
       
         // returns a string representation of the specified integer with radix 10
         String retval = i.toString(30, 10);
         System.out.println("Value = " + retval);
         
         // returns a string representation of the specified integer with radix 16
         retval = i.toString(30, 16);
         System.out.println("Value = " + retval);
         
         // returns a string representation of the specified integer with radix 8
         retval = i.toString(30, 8);
         System.out.println("Value = " + retval);
       }
    } 

    返回结果:

    Value = 30 Value = 1e Value = 36

    如果基数小于Character.MIN_RADIX或大于Character.MAX_RADIX的,则基数10代替.

    这个地方MIN_RADIX不能为1,是因为基数不能为1,如果基数为1,就会进入死循环,1都不管多少次方都不可能成为不是1的其它数值

    下面的ASCII字符被用来作为数字: 0123456789abcdefghijklmnopqrstuvwxyz

    将整数转换为16进制

     public static String toHexString(int i) {
            return toUnsignedString(i, 4);
        }

    这 个地方解释一下为什么是4,因为16=2^4,操作:先将1向左移动4位即radix = 1 <<4 ,得到二进制10000,然后减去1,得到掩码mask=1111,这个mask就是用来与要转换整数,从低到高位,每四位一次进行&操作,这样 没四位与一次,得到一个16进制数值,直到所有的二进制转换为16进制为止。

    将整数转换为8进制

     public static String toOctalString(int i) {
            return toUnsignedString(i, 3);
        }

    这个地方的3就是因为转换为8进制,8 = 2 ^3,调用与16进制相同的方法。

    将整数转换为二进制:

    public static String toBinaryString(int i) {
            return toUnsignedString(i, 1);
        }

    这个地方的1同上,2 = 2^1,调用方法都是相同的

    这个地方就是进制转换的时候调用的方法,i就是要进行转换的10进制数,shift就是那个4,3,1

    radix就是将1向左移动几位,mask就是得到用来转换用的掩码

      private static String toUnsignedString(int i, int shift) {
            char[] buf = new char[32];
            int charPos = 32;
            int radix = 1 << shift;
            int mask = radix - 1;
            do {
                buf[--charPos] = digits[i & mask];
                i >>>= shift;
            } while (i != 0);

            return new String(buf, charPos, (32 - charPos));
        }

    这个地方是将一个整数转换为字符串,Integer.MIN_VALUE = 0x80000000

    其中getChars是一个比较有趣的方法,将整数转换后放在buf中

     public static String toString(int i) {
            if (i == Integer.MIN_VALUE)
                return "-2147483648";
            int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
            char[] buf = new char[size];
            getChars(i, size, buf);
            return new String(buf, true);
        }

     static void getChars(int i, int index, char[] buf) {
            int q, r;
            int charPos = index;
            char sign = 0;

            if (i < 0) {
                sign = '-';
                i = -i;
            }

            // Generate two digits per iteration
            while (i >= 65536) {  
                q = i / 100;
            // really: r = i - (q * 100);
                r = i - ((q << 6) + (q << 5) + (q << 2));
                i = q;
                buf [--charPos] = DigitOnes[r];   //求的个位数
                buf [--charPos] = DigitTens[r];     //求的十位数
            }

            // Fall thru to fast mode for smaller numbers
            // assert(i <= 65536, i);
            for (;;) {
                q = (i * 52429) >>> (16+3);                                         //这个地方52429数字非常神奇!!!!!!!!!!!!!!!
                r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
                buf [--charPos] = digits [r];
                i = q;
                if (i == 0) break;
            }
            if (sign != 0) {
                buf [--charPos] = sign;
            }
        }

    用来计算十位数

     final static char [] DigitTens = {
            '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
            '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
            '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
            '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
            '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
            '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
            '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
            '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
            '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
            '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
            } ;

    用来计算个位数

     final static char [] DigitOnes = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            } ;

     

    用来计算可以代表的字符

     final static char[] digits = {
            '0' , '1' , '2' , '3' , '4' , '5' ,
            '6' , '7' , '8' , '9' , 'a' , 'b' ,
            'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
            'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
            'o' , 'p' , 'q' , 'r' , 's' , 't' ,
            'u' , 'v' , 'w' , 'x' , 'y' , 'z'
        };

    用来计算这个数是几位的数字

    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                          99999999, 999999999, Integer.MAX_VALUE };

    这个用来判断一个正数,判断这是几位数,正好调用上面的sizeTable

    static int stringSize(int x) {
            for (int i=0; ; i++)
                if (x <= sizeTable[i])
                    return i+1;
        }

    下面这个方法是将一个radix进制的s转换成十进制的整数

    比如s为32,radix 为4,那么最后转换成的整数时3*4+2 = 14;

    这个地方会因为字符串不满足格式个出现异常,所以首先抛出NUmberFormatException异常

    / * @param      s   the {@code String} containing the integer
         *                  representation to be parsed
         * @param      radix   the radix to be used while parsing {@code s}.
         * @return     the integer represented by the string argument in the
         *             specified radix.
         * @exception  NumberFormatException if the {@code String}
         *             does not contain a parsable {@code int}.
         */
        public static int parseInt(String s, int radix)
                    throws NumberFormatException
        {
            /*
             * WARNING: This method may be invoked early during VM initialization
             * before IntegerCache is initialized. Care must be taken to not use
             * the valueOf method.
             */

    //这个地方当输入为null或者输入radix为小于2或者大于36都是不允许的,都会抛出异常
            if (s == null) {
                throw new NumberFormatException("null");
            }

            if (radix < Character.MIN_RADIX) {
                throw new NumberFormatException("radix " + radix +
                                                " less than Character.MIN_RADIX");
            }

            if (radix > Character.MAX_RADIX) {
                throw new NumberFormatException("radix " + radix +
                                                " greater than Character.MAX_RADIX");
            }

            int result = 0;
            boolean negative = false;
            int i = 0, len = s.length();
            int limit = -Integer.MAX_VALUE;
            int multmin;
            int digit;

            if (len > 0) {

                //这个地方单独出去第一个字符是用来判断这个是否是符号标示,如果是“-”或者“+”,那么他们<'0'

                char firstChar = s.charAt(0);
                if (firstChar < '0') { // Possible leading "+" or "-"
                    if (firstChar == '-') {
                        negative = true;
                        limit = Integer.MIN_VALUE;
                    } else if (firstChar != '+')
                        throw NumberFormatException.forInputString(s);
                    //如果是+或者-,但长度是1的话也是不允许的,所以会报错
                    if (len == 1) // Cannot have lone "+" or "-"
                        throw NumberFormatException.forInputString(s);
                    i++;
                }
                multmin = limit / radix;
                while (i < len) {
                    // Accumulating negatively avoids surprises near MAX_VALUE
                    digit = Character.digit(s.charAt(i++),radix); 这个地方讲解放在这个方法的最后

                    //每个字符都要判断是否符合格式,如果有某个字符不符合格式也不是不能进行转换操作的

                    if (digit < 0) {
                        throw NumberFormatException.forInputString(s);
                    }
                    if (result < multmin) {
                        throw NumberFormatException.forInputString(s);
                    }
                    result *= radix;
                    if (result < limit + digit) {
                        throw NumberFormatException.forInputString(s);
                    }
                    result -= digit;
                }
            } else {
                throw NumberFormatException.forInputString(s);
            }
            return negative ? result : -result;
        }

    java.lang.Character.digit(char ch, int radix)API

    public static int digit(char ch,
                            int radix)

      • 返回使用指定基数的字符 ch 的数值。

        如果基数不在 MIN_RADIX <= radix <= MAX_RADIX 范围之内,或者 ch 的值是一个使用指定基数的无效数字,则返回 -1。如果以下条件中至少有一个为真,则字符是一个有效数字:

        • 方法 isDigittrue,且字符(或分解的单字符)的 Unicode 十进制数值小于指定的基数。在这种情况下,返回十进制数值。        

        • 字符为 'A''Z' 范围内的大写拉丁字母之一,且它的代码小于 radix + 'A' - 10。在这种情况下,返回 ch - 'A' + 10。        

        • 字符为 'a''z' 范围内的小写拉丁字母之一,且它的代码小于 radix + 'a' - 10。在这种情况下,返回 ch - 'a' + 10

             

    这个地方从返回就可以看出来 parseInt(String s)实际上是parseInt(String s, int radix)的特出情况,及radix为10的时候

     public static int parseInt(String s) throws NumberFormatException {
            return parseInt(s,10);
        }

     public static Integer valueOf(String s) throws NumberFormatException {
            return Integer.valueOf(parseInt(s, 10));
        }

    这 个地方可以清楚的看到value(String s ,int radix)先返回valueof(int i),而valueof(int i)又调用了parseInt(String s,int radix)所以本质上还是执行了parseInt(String s,int radix)

    public static Integer valueOf(String s, int radix) throws NumberFormatException {
            return Integer.valueOf(parseInt(s,radix));
        }

    IntegerCache是Integer的内部类,用来将-128——high之间的对象进行实例化

     private static class IntegerCache {
            static final int low = -128; //缓存下届,不可改变了,只有上届可以改变
            static final int high;
            static final Integer cache[];

            static {
                // high value may be configured by property
                int h = 127;//h值,可以通过设置jdk的AutoBoxCacheMax参数调整(以下有解释),自动缓存区间设置为[-128,N]。注意区间的下界是固定 
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);// 取较大的作为上界,但又不能大于Integer的边界MAX_VALUE
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low));
                }
                high = h;

                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
            }

            private IntegerCache() {}
        }

    这个方法就是用来调用上面缓存里面的对象,如果整数值在缓存对象数组范围内,就直接返回缓存对象,如果不在里面,就要为其新建对象

    Integer i= 5;这是自动装箱问题,java运行的就是下面这段代码

     public static Integer valueOf(int i) {
            assert IntegerCache.high >= 127;
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }

    构造方法,默认执行是parse(Stirng s, int 10)方法。

    public Integer(String s) throws NumberFormatException {
            this.value = parseInt(s, 10);
        }

    //比较两个整数是否相等,首先判断被比较对象是否是整型实例,如果是,将其转换成int类型进行比较

     public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }

    //

    public static Integer getInteger(String nm, Integer val)返回具有指定名称的系统属性的整数值。

    第一个参数被视为系统属性的名称。通过 System.getProperty(java.lang.String) 方法可以访问系统属性。然后,根据每个 Integer.decode 方法,将该属性的字符串值解释为一个整数值,并返回一个表示该值的 Integer 对象。 如果属性值以两个 ASCII 字符 0x 或者 ASCII 字符 # 开始,并且后面没有减号,则将它的剩余部分解析为十六进制整数,就好像以 16 为基数调用 valueOf(java.lang.String, int) 方法一样。

    如果属性值以 ASCII 字符 0 开始,后面还有其他字符,则将它解析为八进制整数,就好像以 8 为基数调用 valueOf(java.lang.String, int) 方法一样。

    否则,将属性值解析为十进制整数,就好像以 10 为基数调用 valueOf(java.lang.String, int) 方法一样。

    第二个参数是默认值。如果未具有指定名称的属性,或者属性的数字格式不正确,或者指定名称为空或 null,则返回默认值。

     

     public static Integer getInteger(String nm, Integer val) {
            String v = null;
            try {
                v = System.getProperty(nm);//这个方法的解析放到System类中
            } catch (IllegalArgumentException e) {
            } catch (NullPointerException e) {
            }
            if (v != null) {
                try {
                    return Integer.decode(v); //这个方法在下面进行具体介绍
                } catch (NumberFormatException e) {
                }
            }
            return val;
        }

    //这个方法是调用上面的方法,并且是使第二个参数的默认值为null

     public static Integer getInteger(String nm) {
            return getInteger(nm, null);
        }

    //这个地方实际上是先调用的最上面的方法,同样也是使第二个参数为null,然后根据返回结果,如果是null,将第二个参数转换成Integer类型返回

     public static Integer getInteger(String nm, int val) {
            Integer result = getInteger(nm, null);
            return (result == null) ? Integer.valueOf(val) : result;
        }

     

    //这个方法是方法解码字符串转换为整数,(1)判断长度如果是0,则抛出0长度异常,(2)判断其第一个字符是'-'还是'+',

    (3)调用String.startWith(String s,int i)方法,判断这是多少进制的数值(4)如果第二个字符又出现了'-'或是'+',则抛出符号位置异常

    (5)调用Integer.valueof(String s, int i)方法,将其解码为十进制整数(6)根据其正负值,返回相应的数值

    (7)最后抛出的异常是如果转换的整数刚好是Integer.MIN_VALUE,因为正数不包含,所以抛出异常,需要在异常中获取返回

    public static Integer decode(String nm) throws NumberFormatException {
            int radix = 10;
            int index = 0;
            boolean negative = false;
            Integer result;

            if (nm.length() == 0)
                throw new NumberFormatException("Zero length string");
            char firstChar = nm.charAt(0);
            // Handle sign, if present
            if (firstChar == '-') {
                negative = true;
                index++;
            } else if (firstChar == '+')
                index++;

            // Handle radix specifier, if present
            if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
                index += 2;
                radix = 16;
            }
            else if (nm.startsWith("#", index)) {
                index ++;
                radix = 16;
            }
            else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
                index ++;
                radix = 8;
            }

            if (nm.startsWith("-", index) || nm.startsWith("+", index))
                throw new NumberFormatException("Sign character in wrong position");

            try {
                result = Integer.valueOf(nm.substring(index), radix);
                result = negative ? Integer.valueOf(-result.intValue()) : result;
            } catch (NumberFormatException e) {
                // If number is Integer.MIN_VALUE, we'll end up here. The next line
                // handles this case, and causes any genuine format error to be
                // rethrown.
                String constant = negative ? ("-" + nm.substring(index))
                                           : nm.substring(index);
                result = Integer.valueOf(constant, radix);
            }
            return result;
        }

    //比较两个整数,如果小于返回-1,相等返回0,大于返回1

     public static int compare(int x, int y) {
            return (x < y) ? -1 : ((x == y) ? 0 : 1);
        }

    //实际上是调用的compare方法

     public int compareTo(Integer anotherInteger) {
            return compare(this.value, anotherInteger.value);
        }

    1.第一步的作用是把最高位1右移移位,并与原数据按位取或。那么这就使得最高位和它的下一位是连续两个1。

    2、第二步的作用是把刚刚移位得到连续两个1继续右移两位并与原数据按位取或。那么这就使得最高两位和它的下两个连续位组成四个连续的1。

    3、 以此类推,最终得到的i是从开始的最高位到结束全是1。并减去i不带符号的右移一位,即可得到一个int数据的最高位的值。

    4、上述情况是针对于i不为零和负数的情况,如果i为零,那么得到的结果始终为零。如果i位负数,那么得到的结果始终是-2147483648。即等于Integer.MIN_VALUE。(原因在于负数的最高位始终为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);
        }

     

    //求最低位数值,用这个数字与他的负数进行相与操作,用补码进行相与操作
     public static int lowestOneBit(int i) {
            // HD, Section 2-1
            return i & -i;
        }

    //求得从高位开始到第一个非零数值之间0的个数

    具体做法:

    (1)如果是0,则返回32

    (2)无符号右移16为,如果为0,说明左边这16位都为0,左移16位,将最左边的16删除

    (3)无符号右移24位,如果是0,说明左边的8位都为0,左移8位,将左边的8位删除掉

    (4)无符号右移28位,如果是0,说明左边的4位都为0,左移4位,将左边的4位删除掉

    (5)无符号右移30位,如果是0,说明左边的2位都为0,左移2位,将左边的2位删除掉

    (6)无符号右移31位,如果是0,说明原始数从小到大第二位是0,如果不是,说明是1,将一开始初始化的1减掉

    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

    (1)如果是0,则返回32,否则初始化0的总数为n =  31

    (2)左移16为,如果结果不为0,说明右边这16位存在不为0的值,保存移动之后的结果,接下来继续对其进行移位操作,n = n - 16

    (3)左移8位,如果结果不为0,说明右边的8位存在不为0的值,保存移动之后的结果,接下来继续对其进行移位操作,n = n - 8

    (4)左移4位,如果结果不为0,说明右边的4位存在不为0的值,保存移动之后的结果,接下来继续对其进行移位操作,n = n - 4

    (5)左移2位,如果结果不为0,说明右边的2位存在不为0的值,保存移动之后的结果,接下来继续对其进行移位操作,n = n - 2

    (6)经过上一步结果不为0,说明了最后两位有三种可能,要么其中一位为1,另外一位为0;要么都为1;在这里这用考虑第一种情况就行,

    先左移1位,得到最低位的数值,然后无符号右移31位,这样就能将最低位回复到正常位置

    (7)最后用n减去这个数值,如果这个数值为1,减去之后结果为0,正好返回0;如果这个数值为0,减去结果为1,

     

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

    //这是求解一个整数转换成二进制补码之后,其中1的个数

    二分法,两两一组相加,之后四个四个一组相加,接着八个八个,最后就得到各位之和了。

    第一行是计算每两位中的 1 的个数,并且用该对应的两位来存储这个个数,
    如: 01101100 -> 01011000 ,即先把前者每两位分段 01 10 11 00 ,分别有 1 1 2 0 个1,用两位二进制数表示为 01 01 10 00, 合起来为 01011000.

    第二行是计算每四位中的 1 的个数,并且用该对应的四位来存储这个个数.
    如: 01101100 经过第一行计算后得 01011000 ,然后把 01011000 每四位分段成 0101 1000 ,段内移位相加: 前段 01+01 =10 , 后段 10+00=10, 分别用四位二进制数表示为 0010 0010, 合起来为 00100010 .
    下面的各行以此类推,分别计算每8位,16位,32位中的 1 的个数.
    将 0x55555555, 0x33333333, 0x0f0f0f0f 写成二进制数的形式就容易明白了.

    这个还有个浅显的理解方式:

    (1) 假设转换之后的二进制整数的最后两位是XY,那么无符号右移一位,然后与0101相与之后得到的0X,用原始数据相减之后得到二进制数X(Y-X)(转换 成十进制之后:X+Y,即:两位一组表示1的个数),得到的结果是每两位一组中1的个数,只不过 还是用二进制表示的

    (2)将(1)中的到 的结果,每四位一组,先与0011相与,求得后两位中1的个数,然后加上结果无符号右移两位与0011相与,得到前两位中1 的个数,例子:XYZM(表示的是二进制最后四位),因为(1)中的结果都是两位一组来计算的,所以与0011相与后得到ZM,然后右移之后再相与得到 XY,这样相加的结果就是1的个数(2*X+Y+2*Z+M),最后的结果仍用二进制表示,就将(1)中的两位一组表示变成了四位一组表示

    (3) 这一步先右移四位,然后与原数相加,最后与00001111进行相与操作。实际上就上将两个四位进行求和,然后与1111相与,但是相加的时候都会有两次 重复,所以将其中一次与0000相与。举个例子,0101001100110011,右移之后的数据0000010100110011,因为第二组中 0101+0011,然后与1111相与,所以第一组四位0101与0000相与,这样就避免了重复相加

    (4)将上一步的结果右移8位,然后与之相加,这个地方记住只看第二组跟第四组的结果,因为这两个刚好是原来第一组与第二组的和,第三组与第四组的和

    (5)将上一步的结果右移16位,然后相加,这里只看第二组的最后八位结果,这就是叠加之后的和,其他位都不用看

    (6)最有一步与0x3f相与,因为32位最多只需要5位,这里可以多一位,得到最后的结果

      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);                      //16位一组统计 结果放在 后8位        i = i + (i >>> 16);
            return i & 0x3f;                        // 32位1组统计 结果放在 后16位   

    //这个地方我用了比较长时间来研究

    这个方法的主要作用就是要将i转换成二进制之后,然后将数值先向左移动distance个单位,然后将数值再无符号向右移动【distance的补码后五位的值计算出来的数值(因为int只有32位,所以只有后五位的数值才是有效数字)】的单位,最后将两个结果取或操作。

    举个例子,假设i转换成二进制之后为AB【A:32-distance位数字,B:distance位数字】,经过下面方法之后变成了BA,BA就是所求得的结果

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

    下面这个方法正好与上面相反

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

    这个方法是将所有的位数进行翻转操作,即:0与31互换,1与30互换,。。。。。

    具体操作:

    (1)两位一组,进行互换位置

    (2)四位一组,1与3,2与4互换位置

    (3)八位一组,1与8,2与7,3与6,4与5互换位置

    (4)现在的结果是四个八位数组,将第四个数组移动到第一个位置,将第三个数组移动到第二个位置,将第二个数组移动到第三个位置,第一个数组移动到第四个位置

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

    //返回int值的正负号

    具体操作先将原始数据转换成二进制补码,然后右移31,再将原始数据取负,转换成二进制补码,右移31位,最后进行或操作

    正数返回1,负数返回-1,0返回0

    如果是正数i>>31 的结果是0000。。。。0000,-i>>>31的结果是0000。。。。0001,最后结果就是1

    如果是负数i>>31的结果是1111。。。。1111,-1>>>31的结果是0000。。。。0000,最后的结果是-1

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

    这个地方是以Byte为单位进行互换位置

    将int转换成二进制补码,然后八位一组,分成四组,第一组跟第四组互换位置,二三组互换位置

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

     

  • 相关阅读:
    CF1439E
    CF1446
    CSP2020 游记
    CF1442
    CF1444E
    CF1444
    CF850F Rainbow Balls
    A
    uoj266[清华集训2016]Alice和Bob又在玩游戏(SG函数)
    loj536「LibreOJ Round #6」花札(二分图博弈)
  • 原文地址:https://www.cnblogs.com/wzyxidian/p/4769573.html
Copyright © 2020-2023  润新知