问题:
-
10进制转16进制
输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647 -
16进制转10进制
输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。 -
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.252=0.5----------0
0.52=1--------------1,取到1就结束,因为没有小数部分了
所以0.125的二进制表示位0.001
不一定刚好取到1,如0.33,这是就需要按精度要去取舍了
0.332=0.66----------0
0.662=1.32----------1,取小数部分0.32继续
0.322=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)有两个思路:连除和递归。
- 连除
连除是结合数学运算过程的直接代码表达,首先我们输出的结果是字符串,
十进制转其他就是连除和取余的过程,要注意的一点是转化位大于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;
}
- 递归
这里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 ),如果有第二个参数,其用来指定字符串的基数。