从36进制相加认识java的进制机制

36进制的简单实现。

      public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        String num_a = "zzz";
        String num_b = "2";
        char[] maxLenNums = num_a.length() >= num_b.length() ? num_a.toCharArray() : num_b.toCharArray();
        char[] minLenNums = num_a.length() < num_b.length() ? num_a.toCharArray() : num_b.toCharArray();
        Integer oneMore = 0;
        for (int index = 0; index < maxLenNums.length; index++) {
            Map<String, Integer> map = sum(value_10_from_36(maxLenNums[index]),
                    value_10_from_36(getChar(minLenNums, index)), oneMore);
            oneMore = map.get("flag");
            sb.insert(0, JZ_VALUE[map.get("result")]);
        }
        sb.insert(0, oneMore);
        System.out.println(sb);
    }

    private static char getChar(char[] nums, Integer index) {
        if (index < nums.length) {
            return nums[index];
        }
        return 0;
    }

    private static Map<String, Integer> sum(Integer a, Integer b, Integer oneMore) {
        return new HashMap<String, Integer>() {
            private static final long serialVersionUID = 1L;
            {
                put("result", (a + b + oneMore) % 36);
                put("flag", a + b + oneMore > 35 ? 1 : 0);
            }
        };
    }

    private static char[] JZ_VALUE = { '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' };

    private static Integer value_10_from_36(char c) {
        for (int i = 0; i < JZ_VALUE.length; i++) {
            if (JZ_VALUE[i] == c) {
                return i;
            }
        }
        return 0;
    }

java自带的进制转换(附带源码分析)
10进制转2进制 Integer.toBinaryString(n);

    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }
   private static String toUnsignedString0(int val, int shift) {
        //此shift表示 一个进制的一位在2进制中 “ 位数  ”,比如  2进制:1,8进制:3,16进制:4
        //以此来表示需要转换的进制
        // assert shift > 0 && shift <=5 : "Illegal shift value";//Integer最大可支持32进制,,这里有个assert <=5
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);//当前数在二进制中需要的位数,numberOfLeadingZeros获取的是前连续0的个数
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);//chars 表示最后按照指定进制表示的时需要的字符位数
        //一开始也不好理解,直到将shift理解为 ”位数“,mag + (shift - 1)  做个补全措施,
        //弥补上位中需要单独一位表示,但是位数不够的,位数操作就肯定有这个问题,比如,0001 1010 需要转换成16进制,
        //mag= 5  msg/4 = 1,而  0001 1010 需要两位表示的。
        char[] buf = new char[chars];//分配内存
        formatUnsignedInt(val, shift, buf, 0, chars);//这个就是给buf赋值了,
        // Use special constructor which takes over "buf".
        return new String(buf, true);//这个时是1.7才有的方法,后续会在其他地方将这个,protected方法,内部调用时,可以共享内存,进去你会发现,直接复制的。
    }
    public static int numberOfLeadingZeros(int i) {
    //这个方法牛逼之处就是在于各种移位,从高到低,16位前是不是0,,24位前,,,,速度很快
        // 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;
    }
    
   static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {//offset 开始下标
        int charPos = len;//从低位开始
        int radix = 1 << shift;//左移编程 进制
        int mask = radix - 1;//进制下最大数,转成二进制就是 1111...111
        do {
            buf[offset + --charPos] = Integer.digits[val & mask];
            //从低位开始复制,牛逼之处在val & mask,按照进制位数,从低位依次拿对应进制位数下的“数”(比如16进制,1111,一次拿4位)
            val >>>= shift;//排除拿过的4位
        } while (val != 0 && charPos > 0);
        return charPos;
    }

10进制转8进制 Integer.toOctalString(n);

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

一样一样的

10进制转16进制 Integer.toHexString(n);
同理

public static String toOctalString(int i) {
        return toUnsignedString0(i, 4);
    }

10进制转 r 进制 Integer.toString(100, 16);

 public static String toString(int i, int radix) {
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        if (radix == 10) {
            return toString(i);
        }

        char buf[] = new char[33];//最大32位,为啥预留一位?
        boolean negative = (i < 0);
        int charPos = 32;

        if (!negative) {//i始终为负数
            i = -i;
        }

        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];//低位开始 取模操作,
            i = i / radix;
        }
        buf[charPos] = digits[-i];//最后不足取模  digits为进制库,下标代表十进制的数,值代表进制下对应的表示(digits[10] = a)

        if (negative) {
            buf[--charPos] = '-';
        }

        return new String(buf, charPos, (33 - charPos));//截断操作,一般情况下charPos是1
    }

最大32位,为啥预留一位?
因为 int 32位 最小的数:-2147483648 (10000000000000000000000000000000)
这个边界值,转成正数后用Integer来表示还是(10000000000000000000000000000000),前面一个0去掉了,一模一样,
所以兼容它,手动实验

System.out.println(Integer.toString(a, 2))
-10000000000000000000000000000000//33位

N进制转化为十进制 Integer.parseInt(String s,int radix) / Integer.valueOf(String s,int radix)
我告诉你 s 是 radix进制数的 数字 你转成10进制的
两个方法,核心为parseInt
类似以上思想。

利用java API实现

        Integer num_a_10 = Integer.parseInt(num_a, 36);
        Integer num_b_10 = Integer.parseInt(num_b, 36);
        System.out.println(Integer.toString(num_a_10 + num_b_10, 36));

思考:
移位,位运算,代码精简,方法封装,jdk式写代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值