十六进制转八进制的心酸史(java实现)

。。。。十六进制转八进制,转的我的心都累了,自己用了两种方法,结果都是运行超时,哎!最后迫不得已还是借鉴了度娘的代码,在这三次编码中还是学到了很多知识。

方法一:
转换思路:以前学《大学计算机》时,在进制转化这块就学了书上的方法,十六进制转为八进制,十六进制---->十进制----->八进制。于是就按照这个来编码了

编码思路:
十六进制----->十进制:一般的操作方法,就是将十六进制的每一位分别乘以16的多少次方,然后相加。那在计算机中,将十六进制的每一位截取出来,然后判断得到的字符是不是ABCDEF,(我竟然还用了正则表达式),如果是就将他们的ASCALL码值减去55,这样可以得到在十六进制中相应的值,然后再用循环分别得到要乘的16的多少次方。定义一个变量将所有得到值相加。
十进制---->八进制:除k取余,定义remainder来存放余数,quotient来存放商,用一个字符串或者字符数组将所有余数存放起来,当quotient为0时,将字符串逆序输出。

代码实现:

import java.util.Scanner;

public class Mian_sixteentoeight {
	//十六进制转化为十进制
	public int sixteemtoten(String num) {
		int len=num.length();
		int sum=0;
		for(int i=0;i<len;i++) {     //对十六进制的每一个数进行操作
			int number;
			int j=i;
			char a=num.charAt(len-i-1);
			if(65<=a&&a<=70) {      //判断a是否是ABCDEF中的第一
				number=(int)a-55;
			}else {
				number=(int)a-48;
			}	
			//这里是为了实现乘以16的多少次方
			while(j>0) {
				number=number*16;    //时间复杂度是n^2
				j--;
			}
			sum=sum+number;   //将所有的结果相加
		}
		return sum;
	}
	//十进制转化为八进制
	public String tentoeight(int num) {
		int remainder=num%8;
		int quotient=num/8;
		String eight ="";     //            实现逆序输出
		while(quotient!=0) {
			//将int型拼接到String上的三种方法
			eight=eight+remainder;  //字符拼接
			remainder=quotient%8;
			quotient=quotient/8;
		}
		eight=eight+remainder;
		//对字符串进行反转
		char[] str=eight.toCharArray();
		eight="";
		for(int i=str.length-1;i>=0;i--) {
			eight=eight+str[i];    //所以不管是字符串加char还是加int  就直接相加就可以了      这里的时间复杂度也是n^2
		}
		return eight;
	}
	public static void main(String[] args) {
		Mian_sixteentoeight change=new Mian_sixteentoeight();
		Scanner scanner=new Scanner(System.in);
		int n=Integer.parseInt(scanner.nextLine());   //必须是next Line这样下面的收录数据才不会错  
		String[] sixnum=new String[n];
		for(int i=0;i<n;i++) {
			sixnum[i]=scanner.nextLine();
		}
		for(int i=0;i<n;i++) {
			int result=change.sixteemtoten(sixnum[i]);
			System.out.println(result);
			String str=change.tentoeight(result);
			System.out.println(str);
		}
	}
}


上面代码就是我具体实现过程,

在编上面这一段代码我学到的知识:

  • 1.我如果想直接在main函数里面调用函数,可以将函数定义为static ,这样就不用每次创建对象了,然后用对象调用。
  • 2.Java中的正则表达式,String reg=“正则表达式内容” 例:reg="[A-Z]" ,匹配: 字符串.matches(reg)。
  • 3.将char转化为String的方法 String str=String.valueOf(a) a是字符
  • 4.两种将String转换为int型的方法
    int n=Integer.parseInt(字符串);
    int n=Integer.valueOf(字符串).intValue();
  • 5.将int类型的数拼接到字符串上的三种方法: 字符串不管是和int类型还是char 直接相加就可以实现拼接。
    eight=eight+String.valueOf(remainder)
    eight=eight.concat(String.valueOf(remainder));
    eight=eight+remainder;

方法二
将上面的代码拿到测评系统去,结果运行超时。。。。好没办法执行方法二。

转换思路:十六进制----->二进制----->八进制, 这个方法应该就是我在课本上没有学到的简便方法了。

编码思路:四位二进制数表示一个十六进制数,三位二进制数表示一个八进制数,秉承着这样的思想,我弄了两个map集合来存放这样的对应关系,同时写了两个方法来获取对应key的value值,(也可以不用),转换过程都还是挺简单的,中间部分,因为要转为八进制,而三位二进制为一个八进制,所以需要添加0。

代码实现:

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main_sixteentoeight01 {
	private Map<Character,String> sixtotwo=new HashMap<Character,String>();
	private Map <String,Character> twotoeight=new HashMap<String,Character>();
	public Main_sixteentoeight01() {
		sixtotwo.put('0', "0000");
		sixtotwo.put('1', "0001");
		sixtotwo.put('2', "0010");
		sixtotwo.put('3', "0011");		
		sixtotwo.put('4', "0100");
		sixtotwo.put('5', "0101");
		sixtotwo.put('6', "0110");
		sixtotwo.put('7', "0111");
		sixtotwo.put('8', "1000");
		sixtotwo.put('9', "1001");
		sixtotwo.put('A', "1010");
		sixtotwo.put('B', "1011");
		sixtotwo.put('C', "1100");
		sixtotwo.put('D', "1101");
		sixtotwo.put('E', "1110");
		sixtotwo.put('F', "1111");
		
		twotoeight.put("000",'0');
		twotoeight.put("001",'1');
		twotoeight.put("010",'2');
		twotoeight.put("011",'3');
		twotoeight.put("100",'4');
		twotoeight.put("101",'5');
		twotoeight.put("110",'6');
		twotoeight.put("111",'7');

	}
	public String getTwo(Character six) {
		return sixtotwo.get(six);
	}
	public Character getEight(String two) {
		return twotoeight.get(two);
	}
	public void transform(String num) {
		
		//完成到二进制的转化
		int num_len=num.length();
		String temp="";                             //这里应该用String Builder的
		for(int i=0;i<num_len;i++) {
			char a=num.charAt(i);
			temp=temp+getTwo(a);
		}
		
		 //将二进制转化为八进制
		int rest=temp.length()%3;
		while(rest<3&&rest!=0) {     //添加0
			temp='0'+temp;
			rest++;
		}
		if(temp.substring(0,3).equals("000")) {   //判断前三位是否为0,这是为了不出现前导0的情况
			temp=temp.substring(3);
		}
		int len=temp.length();
		for(int i=0;i<len;i=i+3) {       //实现到八进制的转换,并且直接输出结果
			String str=temp.substring(i,i+3);
			System.out.print(getEight(str));
		}
	}
	public static void main(String[] args) {
		Main_sixteentoeight01 change=new Main_sixteentoeight01();
		Scanner scanner=new Scanner(System.in);
		int n=Integer.parseInt(scanner.nextLine());   //必须是next Line这样下面的收录数据才不会错  
		String[] sixnum=new String[n];
		for(int i=0;i<n;i++) {
			sixnum[i]=scanner.nextLine();
		}
		for(int i=0;i<n;i++) {
			change.transform(sixnum[i]);
			System.out.println();
		}
	}
}

以上就是代码实现过程,相对来说操作代码行就少多了。我以为可以通过测评系统了,结果还是超时。。。。。

方法三:
基于上两种方法都超时了,我不得不求助度娘了,看看大佬们的代码

转换思路:和方法二的转换思路是一样的。

编码思路:在十六进制转二进制时,没有用map集合来实现对应的转化关系,而是用switch case(这样可以节省系统空间),在二进制转八进制时,采用了特殊的算法(可能只是我不知道吧) a=(str2.charAt(i)-‘0’)*4+(str2.charAt(i+1)-‘0’)*2+(str2.charAt(i+2)-‘0’);

代码实现:

import java.util.Scanner;  

public class Main_sixteentoeight02 {  
   
    public static void main(String[] args)  
    {  
             Scanner sc=new Scanner(System.in);  
             int n=sc.nextInt();  
             String[] st=new String[n];  
             for(int i=0;i<n;i++)  
             {  
            	 st[i] =sc.next();  
             }  
             sc.close();
             for(int i=0;i<n;i++)  
             {  
                 String str1=ttos(st[i]); 
                 //补全二进制数  这样就好操作 因为后面要进行三个三个来     同时要去掉前导0
                 int len_str1=str1.length();  
                 if(len_str1%3==1)str1="00"+str1;   
                 else if(len_str1%3==2)str1="0"+str1;    //else if 里面可以没有else呢
                 ttoe(str1);  
             }  
    }  
         public static String ttos(String  str)  
         {  
             int len_str=str.length();  
             StringBuilder str2=new StringBuilder();  //因为要对字符串进行多次操作  所以我们用StringBuilder
             for(int i=0;i<len_str;++i)   
             {   
		         switch(str.charAt(i))   
		         {   
		         case '0':str2.append("0000");break;   
		         case '1':str2.append("0001");break;   
		         case '2':str2.append("0010");break;   
		         case '3':str2.append("0011");break;   
		         case '4':str2.append("0100");break;   
		         case '5':str2.append("0101");break;   
		         case '6':str2.append("0110");break;   
		         case '7':str2.append("0111");break;   
		         case '8':str2.append("1000");break;   
		         case '9':str2.append("1001");break;   
		         case 'A':str2.append("1010");break;   
		         case 'B':str2.append("1011");break;   
		         case 'C':str2.append("1100");break;   
		         case 'D':str2.append("1101");break;   
		         case 'E':str2.append("1110");break;   
		         case 'F':str2.append("1111");break;   
		         default:break;   
		         }   
             } return str2.toString();  
         }  
	  public static void ttoe(String str2)  
	  {  
	           int len=str2.length();  
	           int a;  
	           a=(str2.charAt(0)-'0')*4+(str2.charAt(1)-'0')*2+(str2.charAt(2)-'0');  //为了不出现前导0
	           if(a!=0)
	        	   System.out.print(a);            //若a!=0就直接输出了
	           for(int i=3;i<=len-2;i+=3)   
	           {   
		           a=(str2.charAt(i)-'0')*4+(str2.charAt(i+1)-'0')*2+(str2.charAt(i+2)-'0');   
		           System.out.print(a);  
	           }
	           System.out.println();   
	            
	  }  
}

上面就是代码,哎,还是大佬们厉害,终于通过了

学到的知识:

  • 1.将方法定义为static 这样在main方法中调用的时候就直接调用即可
  • 2.输入流要关闭
  • 3.十六进制转化为二进制 不需要用一个集合来存放 就直接switch case 这样可以节约空间
  • 4.十六进制转二进制时 因为对字符是要进行拼接操作 根据十六进制的位数对字符串的操作次数就较多 所以这里我们用的是StringBuiler, 节约空间
  • 5.二进制转八进制的特殊处理方法 需要学会呢
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值