华为机试牛客刷题之HJ5 进制转换
HJ5 进制转换
描述
对于给定的十六进制数,输出其对应的十进制表示。
在本题中,十六进制数的格式为:0x 开头,后跟若干个十六进制数字( 0-9 和 A-F )。其中,A-F 依次代表 10−15 。
输入描述:
在一行上输入一个十六进制数 s ,代表待转换的十六进制数。
保证 s 转化得到的十进制数 x 的范围为 1≦x≦2^31 −1 。
输出描述:
在一行上输出一个整数,代表 s 对应的十进制数。
示例1
输入:0xFA93
输出:64147
说明:
回忆十六进制转化为十进制的方法:从右往左,将第 i 位乘以 16^i ,然后求和。
在这个样例中,0xFA93 的第 0 位是 3 ,第 1 位是 9 ,第 2 位是 A ,第 3 位是 F ,因此 0xFA93=3×16^0 +9×16^1 +10×16^2 +15×16^3 =64147 。
思路是用switch语句处理每个字符的值,从0到F,每个对应的数值乘以16的指数次方,累加到sum中。
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextLine()) { // 注意 while 处理多个 case
// int a = in.nextInt();
String str = in.nextLine();
int len = str.length();
int sum = 0;
for(int k=2;k<len;k++){
int exp = len-k-1;
switch(str.charAt(k)){
case '0':
break;
case '1':
sum += Math.pow(16,exp);
break;
case '2':
sum += 2*Math.pow(16,exp);
break;
case '3':
sum += 3*Math.pow(16,exp);
break;
case '4':
sum += 4*Math.pow(16,exp);
break;
case '5':
sum += 5*Math.pow(16,exp);
break;
case '6':
sum += 6*Math.pow(16,exp);
break;
case '7':
sum += 7*Math.pow(16,exp);
break;
case '8':
sum += 8*Math.pow(16,exp);
break;
case '9':
sum += 9*Math.pow(16,exp);
break;
case 'A':
sum += 10*Math.pow(16,exp);
break;
case 'B':
sum += 11*Math.pow(16,exp);
break;
case 'C':
sum += 12*Math.pow(16,exp);
break;
case 'D':
sum += 13*Math.pow(16,exp);
break;
case 'E':
sum += 14*Math.pow(16,exp);
break;
case 'F':
sum += 15*Math.pow(16,exp);
break;
}
}
System.out.println(sum);
}
}
}
以下是优化的代码:
处理大小写字母、避免精度丢失和整数溢出。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextLine()) {
String str = in.nextLine().toUpperCase(); // 统一转为大写处理
if (!str.startsWith("0X") || str.length() <= 2) {
System.out.println(0);
continue;
}
long sum = 0;
int len = str.length();
int digits = len - 2;
// 计算最高位的权值(16的digits-1次方)
long power = 1;
for (int i = 1; i < digits; i++) {
power *= 16;
}
// 遍历每一位字符
for (int k = 2; k < len; k++) {
char c = str.charAt(k);
int val = 0;
if (c >= '0' && c <= '9') {
val = c - '0';
} else if (c >= 'A' && c <= 'F') {
val = 10 + (c - 'A');
} else {
System.out.println(0); // 非法字符处理
return;
}
sum += val * power;
power /= 16; // 权值递减
}
System.out.println(sum);
}
}
}
关键修改说明
-
大小写处理
- 使用
toUpperCase()
将输入统一转为大写,避免漏掉小写字母(如a-f
)。
- 使用
-
输入校验
- 检查输入是否以
0X
开头且长度合法,否则输出0
(根据题目要求可能需要调整)。
- 检查输入是否以
-
手动计算权值
- 通过循环累乘计算权值(如
16^3, 16^2...
),避免Math.pow()
的精度问题。
- 通过循环累乘计算权值(如
-
使用 long 类型
sum
和power
使用long
类型,防止大数溢出。
示例验证
-
输入
0x1A
转换过程:1*16^1 + 10*16^0 = 26
,输出26
。 -
输入
0xFF
转换过程:15*16^1 + 15*16^0 = 255
,输出255
。 -
输入
0x7FFFFFFF
转换结果:2147483647
(Integer.MAX_VALUE
),用long
正确存储。