摘要
我们日常常用的是十进制。
计算机是基于二进制的,计算机常用的还有十六进制、八进制。
本文主要介绍如何实现十进制和任意进制间转换。
计算思想
如果用:【0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ你我】分别代表数字。则A代表36,你代表62,我代表63.
1、任意进制转10进制。比如64进制:A你我,可分解为
A你我 = 我*1+你*64+A*64*64=63*1+62*64+36*64*64=151487;
2、10进制转任意进制。还是151487。
y=m*r^x = m0*1+m1*64+m2*64^2+m3*64*3+...mi*64^i=151487,我们需要计算出所有次幂x及对应的乘数m.
我们先算用算出它的最高次幂,x=log(151487)/log(64),取整为2,即最大次幂为2。
计算出对应乘数m2=151487/64^2,取整为36。
计算余数=151487对36*64^2取余数。
对余数分别再用上面的方法计算,即可获得所有的乘数和次幂。分别是:2次幂-36,1次幂-62,0次幂-63。 即结果为:36,62,63,对应字符串为:A你我。
注意:中间如果有某些次幂不存在,也需要补0作为乘数。如:5*64^5+3*64^1=5*64^5+0*64^4+0*64^3+0*64^2+3*64^1+0*64^0=500030
代码实现
任意进制转10进制:
/**
* 任意进制转换成十进制
* @param num 要转换的任意进制数字
* @param radix 当前要转换的数字进制
* @param dict 目标进制数值和字符对应关系,如:0-0 a-10 z-35
* @return
*/
public static int radixConvert10(String num, int radix, Map<String, Integer> dict){
String[] nums = num.split("");
int result=0;
for(int i=0; i<nums.length; i++){
// y=m*r^x = m0*r^0+m1*r^1+m2*r^2+...+mi*r^i+...
// 从后往前累加
String mi_str = nums[nums.length-i-1];
int mi=dict.get(mi_str);
result += mi*Math.pow(radix,i);
}
return result;
}
/**
* 任意进制转换成十进制
* @param num 要转换的10进制数字
* @param radix 目标进制
* @param numberOrder 目标进制代替数字的字符串顺序,如:0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
* @return
*/
public static int radixConvert10(String num, int radix, String numberOrder){
String[] split = numberOrder.split("");
Map<String, Integer> dict = new HashMap<>();
//做字符串和数字的对应关系
for(int i=0; i<split.length; i++){
dict.put(split[i],i);
}
return radixConvert10(num, radix, dict);
}
十进制转任意进制:
/**
* 十进制转换成任意进制
* @param num 要转换的10进制数字
* @param radix 目标进制
* @param dict 目标进制数值和字符对应关系,如:0-0 10-a 35-z
* @return
*/
public static String radixConvert(int num, int radix, Map<Integer, String> dict){
if(num<radix){
//个位数,直接获取
return dict.get(num);
}
int temp = num;
int prex=0;
List<Integer> ms = new ArrayList<>();
while (temp>0){
// 获取最大的幂, 如m*r^x
int x = (int)(Math.log(temp) / Math.log(radix));
// 获取该幂的乘数
int m = (int)(temp / Math.pow(radix, x));
// 如果前一次幂比后一次幂大超过1
while (prex>x+1){
ms.add(0);
prex--;
}
prex=x;
ms.add(m);
// 取余,再循环进行下一次幂运算
temp = temp % (m * (int)Math.pow(radix, (x)));
}
while (prex>0){
ms.add(0);
prex--;
}
StringBuilder sb = new StringBuilder();
for(Integer m:ms){
sb.append(dict.get(m));
}
return sb.toString();
}
/**
* 十进制转换成任意进制
* @param num 要转换的10进制数字
* @param radix 目标进制
* @param numberOrder 目标进制代替数字的字符串顺序,如:0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
* @return
*/
public static String radixConvert(int num, int radix, String numberOrder){
String[] split = numberOrder.split("");
Map<Integer, String> dict = new HashMap<>();
//做字符串和数字的对应关系
for(int i=0; i<split.length; i++){
dict.put(i,split[i]);
}
return radixConvert(num, radix, dict);
}
测试:
public static void main(String[] args) {
String numberOrder = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ你我";
String num="A你我";
int n = radixConvert10(num, 64, numberOrder);
System.out.println(num+"(64进制)="+n+"(10进制)");
String s = radixConvert(n, 64, numberOrder);
System.out.println(n+"(10进制)="+s+"(64进制)");
}
运行结果:
A你我(64进制)=151487(10进制)
151487(10进制)=A你我(64进制)
暂不支持负数,负数可先去掉符号转成正数,然后再计算。任意进制转换的作用和意义,这里不作解释。
***********************************************************************************************
author:蓝何忠
email:lanhezhong@163.com
***********************************************************************************************