题目描述
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。注意:
十六进制中所有字母(a-f)都必须是小写。
十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符’0’来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。
给定的数确保在32位有符号整数范围内。
不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。
样例描述
示例 1:
输入:
26
输出:
"1a"
示例 2:
输入:
-1
输出:
"ffffffff"
思路
方法一:通用模拟进制转化
- 通用的进制转化思路,用原数%k,原数/k来不断构造出转化后的每一位。
- 对于负数,要处理补码问题。要加上
2^32
的偏移量,为了防止溢出,加之前先设置为long型。然后再进行上面的进制转化。 - 最后记得翻转。
方法二:位运算 + 分组换算
- 由于16进制数,相当于二进制数的每四位成一组对应成一个十六进制数。所以可以分成八组依次进行换算。具体就是用原数与0x1111(就是15)做&运算,可以取出末尾的四位,进行转化为十六进制数,然后对原数做无符号右移四位,(>>>)。直到原数为0即可。
- 因为本身就是对32位二进制数进行操作,而机器中二进制数本身就是用补码来表示的,所以无需处理负数的补码问题。
- 细节,一定是无符号右移,这样才能让原数最后为0,否则补上符号,负数的话高位是补1。
代码
方法一:
class Solution {
public String toHex(int _num) {
if (_num == 0) return "0";
//先转化为long
long num = _num;
StringBuffer res = new StringBuffer();
//处理负数,加上偏移换成补码。 防止溢出,转为long
if (num < 0) num = (long)(Math.pow(2, 32) + num);
//通用的进制转化法
while (num != 0) {
long t = num % 16;
if (t >= 10) res.append((char)(t - 10 + 'a'));
else res.append((char)(t + '0'));
num /= 16;
}
return res.reverse().toString();
}
}
方法二:
class Solution {
public String toHex(int num) {
if (num == 0) return "0";
StringBuilder res = new StringBuilder();
while (num != 0) {
//取出末尾四位
int t = num & 15; // num & (0x1111)是错误的,因为进制不同的数不能做与运算
//如果大于10,就转化为字母
if (t >= 10) {
res.append((char)(t - 10 + 'a'));
}
else res.append((char)(t + '0'));
//无符号右移四位
num >>>= 4;
}
//记得翻转,因为前面先处理的是低位但是放在了结果集的前面
return res.reverse().toString();
}
}