问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
思路分析
首先,遇到问题肯定是将问题化为一个一个的小问题,逐个解决。
问题一:根据提示可知需要将十六进制先转换为某进制,那么这个某进制是几?
答:我们最为熟悉的进制转换问题莫过于二进制转某进制或某进制转二进制,因此不难确定这个某进制便是二进制。
问题二:怎样将十六进制转换为二进制?
答:将所给的十六进制数放在数组中,利用循环逐位判断,逐位赋值。利用StringBuilder(不用StringBuffer的原因是因为StringBuilder速度更快,且绝大多数场景下不需要线程安全。)将转换后的字符串返回即可。
问题三:怎样将二进制转换为八进制?
答:原理同上,需要注意的是,十六进制为四位数的二进制数,而八进制为三位数的二进制数。因此在逻辑判断上有一定的区别。
问题四:怎样处理前导零?
答:很简单,在转换为二进制后进行一个判断,不足则补即可。
解法:先转换为二进制后转换为八进制
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//因测试用例中数字过大,所以使用字符串类型
String[] str = new String[n];
//字符串类型里length是方法,数组里length是属性,因此调用时不需加括号
for(int i=0; i<str.length; i++){
str[i] = sc.next();
}
for(int i=0; i<str.length; i++){
//十六进制转换为二进制
String strByarr = to_2(str[i]);
//八进制是三个二进制为一组,所以对长度以三为底取余,将不够的位数补齐
//注意:不是三的整数倍在前面补0
if(strByarr.length()%3==1){
strByarr="00"+strByarr;
}
if(strByarr.length()%3 ==2){
strByarr="0"+strByarr;
}
//二进制转换为八进制
String strOctal=to_8(strByarr);
//输出
System.out.println(strOctal);
}
}
public static String to_2(String str){
StringBuilder sBuilder = new StringBuilder();
for(int i=0; i<str.length(); i++){
switch (str.charAt(i)){ //截取十六位的每一个字符并将其转换为二进制
case '0':
sBuilder.append("0000");
break;
case '1':
sBuilder.append("0001");
break;
case '2':
sBuilder.append("0010");
break;
case '3':
sBuilder.append("0011");
break;
case '4':
sBuilder.append("0100");
break;
case '5':
sBuilder.append("0101");
break;
case '6':
sBuilder.append("0110");
break;
case '7':
sBuilder.append("0111");
break;
case '8':
sBuilder.append("1000");
break;
case '9':
sBuilder.append("1001");
break;
case 'A':
sBuilder.append("1010");
break;
case 'B':
sBuilder.append("1011");
break;
case 'C':
sBuilder.append("1100");
break;
case 'D':
sBuilder.append("1101");
break;
case 'E':
sBuilder.append("1110");
break;
case 'F':
sBuilder.append("1111");
break;
}
}
return sBuilder.toString();
}
public static String to_8(String str){
int k=0;
StringBuilder sBuilder = new StringBuilder();
/*若传进来数为十六进制的1,则转换为二进制为0001
以3取余并相加后变为"000001"
若不处理,转换为八进制后为"01"
直接输出不符合题意
*/
if(str.substring(0,3).equals("000")){
k=3;
}
for(int i=k; i<str.length()-2; i+=3){
if("000".equals(str.substring(i,i+3))){
sBuilder.append("0");
//因此将其作为特例,将k设为3,直接忽视掉前三位0,将二进制直接转换为8进制的数进行判断
} else if("001".equals(str.substring(i,i+3))){
sBuilder.append("1");
} else if("010".equals(str.substring(i,i+3))){
sBuilder.append("2");
} else if("011".equals(str.substring(i,i+3))){
sBuilder.append("3");
} else if("100".equals(str.substring(i,i+3))){
sBuilder.append("4");
} else if("101".equals(str.substring(i,i+3))){
sBuilder.append("5");
} else if("110".equals(str.substring(i,i+3))){
sBuilder.append("6");
} else if("111".equals(str.substring(i,i+3))){
sBuilder.append("7");
}
}
return sBuilder.toString();
}
}