本文主要讲解整数的进制转换问题。方便的是,对于低精度整数,java中的整型基类Integer
和Long
中的parseXXX()
方法和valueOf()
方法可以将2 ~ 36进制的字符串转化为十进制整数,toString()
方法可以将10进制数转化为2 ~ 36进制的字符串。对于高精度数,java中的大数类中也包含可以将2 ~ 36进制的字符串转化为BigInteger的构造函数。
对于二进制数 1001 1001 1001,将其转化为十进制的一般做法: 1 ∗ 2 3 + 0 ∗ 2 2 + 0 ∗ 2 1 + 1 ∗ 2 0 1*2^3 + 0*2^2 + 0*2^1 + 1*2^0 1∗23+0∗22+0∗21+1∗20
同样,对于一个 P P P进制的数,我们同样可以这样做。
将一个 P P P进制的数 a 1 a 2 . . . a n a_1a_2...a_n a1a2...an转化为十进制的数 Y Y Y的通式: Y = a 1 ∗ p n − 1 + a 2 ∗ p n − 2 + . . . + a n ∗ p 0 Y = a_1*p^{n-1} + a_2*p^{n-2} +...+ a_n*p^{0} Y=a1∗pn−1+a2∗pn−2+...+an∗p0
但是,一般我们需要转化的进制都是大于10进制的,一般用A表示10,B表示11,以此类推。此时我们只需要特殊判断一下该字母对应的数字是几就可以了。
先给出使用java类中的内置方法的代码:
// 如果题目要进行转化的进制在2~36之间的话直接调用库函数就行了。
String s = in.readLine();
int a = Integer.parseInt(s, 16) // 将16进制的字符串转化十进制数
//BigInteger a = new BigInteger(s, 16);// 高精度数
out.write(Integer.toString(a, 8)); // 转化为8进制输出
//out.write(a.toString(8));
out.flush();
使用进制转化通式:
public static int Int(char c)
{
if(c >= '0' && c <= '9') return c - '0';
return c >= 'a' && c <= 'z' ? c - 'a' + 10 : c - 'A' + 10;
}
public static long ToTen(String x, int p) throws IOException{
long y = 0, b = 1;
for(int i = x.length() - 1; i >= 0; i--)
{
y += Int(x.charAt(i))*b;
b *= p;
}
return y;
}
同样,我们先类比十进制转二进制,也就是用除2取余法。
对于十进制数 17 17 17, 转化为2进制:
对于十进制转化为任意进制的数,仍用取余法。
将十进制数 X X X转化为 P P P进制的数 Y Y Y:用 X X X对 P P P取余,直到商为0,倒序排列余数.
代码:
public static String f(int c)
{
if(c >= 0 && c <= 9) return String.valueOf(c);
return c >= 0 && c <= 9 ? String.valueOf(c) : String.valueOf((char)('A' + c - 10));
}
public static String ToP(int x, int p) throws IOException{
String y = "";
while(true)
{
y = f(x % p) + y;
x /= p;
if(x == 0) break;
}
return y;
}
例题1: 基础练习 十进制转十六进制
例题2: 基础练习 十六进制转十进制
例题3: 基础练习 十六进制转八进制
import java.io.*;
import java.math.*;
public class Main{
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static String f(int c)
{
if(c >= 0 && c <= 9) return String.valueOf(c);
return c >= 0 && c <= 9 ? String.valueOf(c) : String.valueOf((char)('A' + c - 10));
}
public static String ToP(int x, int p) throws IOException{
String y = "";
while(true)
{
y = f(x % p) + y;
x /= p;
if(x == 0) break;
}
return y;
}
public static void main(String[] args )throws IOException{
String s = in.readLine();
out.write(ToP(Integer.parseInt(s), 16) + "");
out.flush();
}
}
import java.io.*;
import java.math.*;
public class Main{
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static int Int(char c){
if(c >= '0' && c <= '9') return c - '0';
return c >= 'a' && c <= 'z' ? c - 'a' + 10 : c - 'A' + 10;
}
public static long ToTen(String x, int p) throws IOException{
long y = 0, b = 1;
for(int i = x.length() - 1; i >= 0; i--)
{
y += Int(x.charAt(i))*b;
b *= p;
}
return y;
}
public static void main(String[] args )throws IOException{
String s = in.readLine();
out.write(ToTen(s, 16) + "");
out.flush();
}
}
此题有两种做法,第一种使用java大数类的进制转化方法。 第二种先将十六进制转化为二进制,然后再转化为八进制。
为什么不转化为十进制呢? 因为本题涉及到高精度数,转化为10进制数需要用到高精度算法,比较麻烦。
方法一:
因为字符串长度很大,所以用快速输入输出。
import java.util.*;
import java.io.*;
import java.math.*;
public class Main{
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] agrs) throws IOException{
String s = in.readLine();
int n = Integer.parseInt(s);
for(int i = 0; i < n; i++){
s = in.readLine();
BigInteger b = new BigInteger(s, 16);
out.write(b.toString(8).toUpperCase()+"\n");
out.flush();
}
}
}
方法二:
先转化为二进制然后转化为八进制,二进制数每4位对应一个16进制数,每3位对应一个八进制数。
二进制转十六进制: 1010001 1010001 1010001 转化为十六进制就是:
所以 101000 1 2 = 5 1 16 1010001_2 =51_{16} 10100012=5116
十六进制转二进制:就是将以上过程颠倒一下,十六进制数的每一位都对应四位的二进制数,然后将所有的二进制数拼接起来就是最终答案。
十六进制数 163 163 163转化为二进制:
所以 16 3 16 = 10110001 1 2 163_{16} = 101100011_{2} 16316=1011000112
对于二进制转八进制,也是同样的方法,只不过是3位二进制数对应一位八进制数。
具体看代码:
import java.io.*;
import java.util.*;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
static Map<String, String> m = new HashMap<>();
static Map<String, String> m1 = new HashMap<>();
static{
m.put("0", "0000");
m.put("1", "0001");
m.put("2", "0010");
m.put("3", "0011");
m.put("4", "0100");
m.put("5", "0101");
m.put("6", "0110");
m.put("7", "0111");
m.put("8", "1000");
m.put("9", "1001");
m.put("A", "1010");
m.put("B", "1011");
m.put("C", "1100");
m.put("D", "1101");
m.put("E", "1110");
m.put("F", "1111");
}
static{
m1.put("000", "0");
m1.put("001", "1");
m1.put("010", "2");
m1.put("011", "3");
m1.put("100", "4");
m1.put("101", "5");
m1.put("110", "6");
m1.put("111", "7");
}
public static int Int(String s){
return Integer.parseInt(s);
}
public static void slove(String s) throws IOException{
StringBuilder res = new StringBuilder();
StringBuilder ans = new StringBuilder();
int lens = s.length();
for(int i = 0; i < lens; i++){ // 转化为2进制串
res.append(m.get(s.substring(i,i+1)));
}
int lenres = res.length(); // 长度
StringBuilder s1 = new StringBuilder();
int cnt = lenres % 3;
if(cnt != 0){ //如果需要补零
while(cnt < 3){
s1.append("0");
cnt += 1;
}
s1.append(res.substring(0, lenres%3));
}
if(s1.length() != 0 && !s1.toString().equals("000")){
ans.append(m1.get(s1.toString()));
}
for(int i = lenres%3; i <= lenres-3; i+=3){
ans.append(m1.get(res.substring(i, i+3)));
}
while(ans.length() > 0 && ans.charAt(0) == '0') ans.delete(0, 1);
out.write(ans + "\n");
out.flush();
}
public static void main(String[] args) throws IOException{
int n;
n = Int(in.readLine());
while(n --> 0){
String s = in.readLine();
slove(s);
}
out.flush();
}
}