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式写代码。