蓝桥志4——进制转换

问题:

  1. 10进制转16进制
    输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647

  2. 16进制转10进制
    输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。

  3. 16进制转8进制
    输入:
    第一行为一个正整数n (1<=n<=10)。
    接下来n行,每行一个由0-9、大写字母A-F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
    输出:
    输出n行,每行为输入对应的八进制正整数。

代码

  • 10转16
pubic class Main{
	public static void main(String[] args){
		Scanner sc  = new Scanner(System.in);
		int n = sc.nextInt();
		int temp = 0;
		String s = "";//用于接收结果
		while(n>=16){
			temp = n%16;
			if(temp>9)
			//余数逆序排列,新的位在字符串前面,所有一定是新位+原来位
				s =(char)('A' + temp - 10) + s;//注意这里要的是字母,分清String.valueOf和(char)的作用
			else
			//不大于9,直接字符串化,加在已有进制位的序列基础上
				s = String.valueOf(temp)+s;
			n = n/16;
		}
		if(n<9)
			s = String.valueOf(temp)+s;
		else
			s =(char)('A' + temp - 10) + s;
	}
}
  • 16转10

思路1:java函数

public class Main{
	Scanner sc  = new Scanner(System.in);
	String s = sc.next();
	System.out.println(Long.valueOf(s,16));
	//或者
	System.out.println(Long.parseLong(s,16));
}

这是基于java的最简单方法,由于直接调用的java函数,所以简单,但这种方式的使用前提是16进制字符串较短,用函数转换时不超出int或long的表示范围。
所以当然有硬算的方法。
思路2:
将输入字符串拆成单个字符存入字符数组,这样每一位的权值也得到了。之后就可以遍历数组算每一位的权值累加即可。

import java.util.Scanner;
    
    public class Main {
    
    	public static void main(String[] args) {
    		Scanner scanner = new Scanner(System.in);
    		String string = scanner.next();
    		char[] c=string.toCharArray();    //将字符串对象中的字符转换为一个字符数组					
    		long sum = 0;	//数据范围上,不超过8位的十六进制数变成10进制会超过int的范围,所以计算总和的sum应该声明为long型,而不是int型,否则会出错。
    		for (int i = 0; i <c.length(); i++) {
    			 if((int)c[i]-'0'>9){//如果字符超过9,具体判断
                     if(c[i]=='A')
                         sum+=10*Math.pow(16,n-i-1);
                     else if(c[i]=='B')
                         sum+=11*Math.pow(16,n-i-1);
                     else if(c[i]=='C')
                         sum+=12*Math.pow(16,n-i-1);
                     else if(c[i]=='D')
                         sum+=13*Math.pow(16,n-i-1);
                     else if(c[i]=='E')
                         sum+=14*Math.pow(16,n-i-1);
                     else if(c[i]=='F')
                         sum+=15*Math.pow(16,n-i-1);
                 }
                 else{
                     sum+=((int)c[i]-'0')*Math.pow(16,n-i-1);
                 }
    		}
    		System.out.println(sum);
    	}
    
    }

  • 16转8
    思路1:java函数
    第一种方法就是用Integer.parseInt(a,b);
    接收字符串a然后以b进制去接受它
    再用Integer.toString(a, b)把a从十进制转换成b进制的数字
    但需要说明的是,这种办法只适用于16进制串较少,能转成int或long的情况,但当16进制字符串过长,像上面要求不超过100000,就要超范围,不能这样做了。
import java.util.Scanner;
public class Hex2Oct {
	public static void main(String[] args) {
		//Integer的parseInt(String s, int i)指定16进制接收字符串解析成10进制的int类型
		//toString(int a , int i)指定进制,变成字符串输出
		//这种做法的前提是16进制数的位数较少,转换为10进制不能超出int的表示范围
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		String[] s = new String[n];
		for(int i =  0 ; i < n ; i ++) {
			String st = sc.next();			
			String result = Integer.toString(Integer.parseInt(st, 16), 8);
			//或者用下面的函数 
		// 	String result=Integer.toOctalString(Integer.valueOf(h, 16));
			s[i] = result;
		}
		for(int i = 0 ; i < n ; i++) {
			System.out.println(s[i]);
		}
	}
}

思路2:
老老实实算,写出各种进制的表,这里就要用到二进制和八进制的关系了,1位16进制数用4位2进制表示,3位2进制表示1位8进制数。
这道题就是先把16进制转换成2进制,再按照对应的方法取8进制对应的值

	public static void main(String[] args) {
		// 接受输入 n
		Scanner scanner = new Scanner(System.in);
		String input_n = scanner.nextLine();
		int n = Integer.parseInt(input_n);

		// 接受输入十六进制数的字符串
		String[] input_nums = new String[n];
		for (int i = 0; i < n; i++) {
			input_nums[i] = scanner.nextLine();
		}
		scanner.close();
		// 十六进制表
		String[] HEXs = { 
			"0", "1", "2", "3", "4", "5", "6", "7", 
			"8", "9", "A", "B", "C", "D", "E", "F"
		};
		// 二进制表
		String[] BINs = { 
			"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", 
			"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" 
		};
		// 八进制表
		String[] OCTs = { 
			"0", "1", "2", "3", "4", "5", "6", "7"
		};
		
		// 十六进制表和二进制表,在所有成员上值一一对应
		// 十六进制表、二进制表和八进制表,在前八位成员上值一一对应

		for (int m = 0; m < n; m++) { // 遍历每个十六进制数字
			String hex = input_nums[m]; // 十六进制表示形式
			StringBuffer sbBin = new StringBuffer();
			StringBuffer sbOct = new StringBuffer();

			// 十六进制转二进制
			// 将十六进制数每一位转换成四位的二进制数字
			for (int i = 0; i < hex.length(); i++) { // 遍历每个十六进制位
				String c = Character.toString(hex.charAt(i));
				// 查询当前位字符在 HEXs中的下标
				int index = Arrays.binarySearch(HEXs, c);
				sbBin.append(BINs[index]);
			}

			// 在二进制数前面插入若干个"0",使得二进数的位数为 3 的倍数
			while (sbBin.length() % 3 != 0) {
				sbBin.insert(0, "0");
			}
			int octLen = sbBin.length() / 3; // 计算目标八进制数的长度
			// 每次取三位二进制数,转换成对应的八进制
			for (int i = 0; i < octLen; i++) {
				String span = sbBin.substring(3 * i, 3 * i + 3);
				int index = Arrays.binarySearch(BINs, "0" + span);
				sbOct.append(OCTs[index]);
			}
			// 此时已经得到结果,需要去除前导 0
			while (sbOct.charAt(0) == '0') {
				sbOct.delete(0, 1);
			}
			System.out.println(sbOct.toString());
		}
	}
}

这3个问题代表了进制转化的3类问题:

  • 10进制转其他进制
  • 其他进制转10进制
  • 其他进制的互换

正好总结一下进制转换问题,总结如下:

十进制转其他进制(常见的如2,8,16)

  • 整数:
    除基取余:除以基数,得到余数,从后往前排列即对应进制数。
    如6转2进制:
    6/2=3-------0
    3/2=1-------1
    1/2=0-------1
    所以6的2进制即110
  • 小数
    乘基取整:乘以基数,取整数部分,将结果的小数部分继续乘以基数,将整数序列从前往后排列即对应进制数。
    如0.125的二进制表示:
    0.1252=0.25-------0
    0.25
    2=0.5----------0
    0.52=1--------------1,取到1就结束,因为没有小数部分了
    所以0.125的二进制表示位0.001
    不一定刚好取到1,如0.33,这是就需要按精度要去取舍了
    0.33
    2=0.66----------0
    0.662=1.32----------1,取小数部分0.32继续
    0.32
    2=0.64----------0
    0.64*2=1.28----------1

其他进制转十进制

位权法:位权展开相加
二进制1001:
1 * 2^3 + 0 * 2 ^ 2+0 * 2 ^ 1 + 1*2 ^ 0

其他进制间的转换(2,8,16)

在这里插入图片描述

代码表达

  • 十进制转其他
    数学运算和代码表达还有一段转化过程,做完这道题我总结了思路如下:
    十进制转其他进制(一般是2~16)有两个思路:连除和递归。
  1. 连除
    连除是结合数学运算过程的直接代码表达,首先我们输出的结果是字符串,
    十进制转其他就是连除和取余的过程,要注意的一点是转化位大于10的进制如16进制时要考虑11,12,,,15转化位A,B,,,F这样的字母的问题。
pubic class Main{
	public static String Direct(int x , int i){
		int temp = 0; 
		String s = "";
		//x为待转化的数,i为目标进制
		while(x>=i){
			temp = x % i ;
			if(temp>9){
				s = (char)('A'+temp-10)+s;
			}else{
				s = String.valueOf(temp)+s;
			}
			x = x/i;
		}
		if (x<9)
			s = String.valueOf(x)+s;
		else
			s = (char)('A'+x-10)+s;
		return s;
}
  1. 递归
    在这里插入图片描述
    这里x是十进制数,i是目标进制数的基数。还是分成两部分,大于基数的部分,要除基取余,小于基数的部分直接取,还是有字母转化的问题。
public class Main{
	public static String Curtion(int x,int i){
		if(x<i){
			if(x>9)
				return (char)('A'+x-10)+"";
			else
				return String.valueOf(x);
		}else{
			if(x%i>9)
				return Curtion(x/i,i)+(char)('A'+x%i-10);
			else
				return Curtion(x/i,i)+String.valueOf(x%i);
		}
	}
}
  • 其他转10进制

类似于上面16进制转10进制,给定x进制的字符串,通过toCharArray()函数转化为字符数组,遍历数组分情况讨论即可。
**(((int)char[i]-‘0’)*Math.pow(x,n-i-1)**是整个算法最核心的一条语句,字符转换为int后变为其Ascii码,减掉字符0即减掉0对应的Ascii码得到字符数字所对应的数字型数字。
+ 小于10进制:直接遍历数组累加即可
+ 等于10:没什么还说的,啥都不用做
+ 大于10:这就要考虑超过10的数位用的是字母表示的情况了,和16进制转10进制类似,具体判断即可。

import java.util.Scanner;
    
    public class Main {
    
    	public static void Others2Dec(String string , int x) {
    		//string为x进制字符串
    		char[] c=string.toCharArray();    //将字符串对象中的字符转换为一个字符数组					
    		long sum = 0;	
    		for (int i = 0; i <c.length(); i++) {
    			if(x<10){
    			 sum+=((int)c[i]-'0')*Math.pow(x,n-i-1);
    			}else if(x==10){
    			System.out.println(string)
    			}else{
    			 if((int)c[i]-'0'>9){//如果字符超过9,具体判断
                     if(c[i]=='A')
                         sum+=10*Math.pow(x,n-i-1);
                     else if(c[i]=='B')
                         sum+=11*Math.pow(16,n-i-1);
                     else if(c[i]=='C')
                         sum+=12*Math.pow(16,n-i-1);
                     else if(c[i]=='D')
                         sum+=13*Math.pow(x,n-i-1);
                     else if(c[i]=='E')
                         sum+=14*Math.pow(x,n-i-1);
                     else if(c[i]=='F')
                         sum+=15*Math.pow(x,n-i-1);
                 }
                 else{
                     sum+=((int)c[i]-'0')*Math.pow(x,n-i-1);
                 }
    		}
    		System.out.println(sum);
    	}
    
    }

  • 其他进制转换
    其他进制间的转换(通常是2,8,16)要以2进制位桥梁,数据规模较小可以直接利用javaNumber类下的各种函数直接完成。较大规模数据就只有老老实实算了。

经验

  • 字符串 + 字符 = 字符串,在java中支持字符串,字符之间的 ‘+’ 运算
  • 字符转为int型后变为其对应的ASCII码。
  • 字符也支持四则运算,其结果是ASCII码的四则运算
  • 数字 + 字符 = 数字,字符会自动类型转换,同经验2,其值为对应ASCII码值。
  • 数字 + 字符串 = 字符串,Java中,数字与字符串相加直接变为字符串。
  • String s的valueOf(char[] x)实现字符数组的字符串化,toCharArray()实现字符拆分存入字符数组。
  • Integer valueOf(String s),从返回值类型可以看出,这个方法用于封装
    Integer valueOf(String s,int i) ,如果有第2个参数,则用来指定字符串的基数
    Integer valueOf(int i),将整数i封装
    其他类型如double,long,float等都有类似方法
  • int parseInt(String s),和上面相反,封装的逆过程,可以称为解封装,将字符串形式的数字做十进制解析。
    int parseInt(Sting s , int i ),如果有第二个参数,其用来指定字符串的基数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值