Convert a Number to Hexadecimal

题目地址:https://leetcode.com/problems/convert-a-number-to-hexadecimal/

Given an integer, write an algorithm to convert it to hexadecimal. For negative integer, two’s complement method is used.

Note:

  1. All letters in hexadecimal (a-f) must be in lowercase.
  2. The hexadecimal string must not contain extra leading 0s. If the number is zero, it is represented by a single zero character ‘0’; otherwise, the first character in the hexadecimal string will not be the zero character.
  3. The given number is guaranteed to fit within the range of a 32-bit signed integer.
  4. You must not use any method provided by the library which converts/formats the number to hex directly.

Example 1:

Input:
26

Output:
"1a"

Example 2:

Input:
-1

Output:
"ffffffff"

题目是将十进制转换为十六进制,整数还是比较好处理的,但是这个题目的关键是负数,要理解负数在计算机中是如何表示的:

public class ConvertANumberToHexadecimal {
    public static final String[] digit= {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    public String toHex(int num) {
        StringBuilder reslut = new StringBuilder("");
        if (num > 0) {
            while (num != 0) {
                reslut.insert(0, digit[num % 16]);
                num /= 16;
            }
        } else if (num == 0){
            reslut.insert(0, "0");
        } else {
            // 以下是截取十六进制每位对应的二进制数值
            // 15 to binnary: 0000 0000 0000 0000 0000 0000 0000 1111
            reslut.insert(0, digit[num & 15]);
            // 240 to binnary: 0000 0000 0000 0000 0000 0000 1111 0000
            reslut.insert(0, digit[(num & 240) >> 4]);
            // 3840 to binnary: 0000 0000 0000 0000 0000 1111 0000 0000
            reslut.insert(0, digit[(num & 3840) >> 8]);
            // 61440 to binnary: 0000 0000 0000 0000 1111 0000 0000 0000
            reslut.insert(0, digit[(num & 61440) >> 12]);
            // 983040 to binnary: 0000 0000 0000 1111 0000 0000 0000 0000
            reslut.insert(0, digit[(num & 983040) >> 16]);
            // 15728640 to binnary: 0000 0000 1111 0000 0000 0000 0000 0000
            reslut.insert(0, digit[(num & 15728640) >> 20]);
            // 251658240 to binnary: 0000 1111 0000 0000 0000 0000 0000 0000
            reslut.insert(0, digit[(num & 251658240) >> 24]);
            // 1879048192 to binnary: 0111 0000 0000 0000 0000 0000 0000 0000
            reslut.insert(0, digit[((num & 1879048192) >> 28) + 8]);
        }
        return reslut.toString();
    }

    public static void main(String[] args) {
        ConvertANumberToHexadecimal hexadecimal = new ConvertANumberToHexadecimal();
        System.out.println(hexadecimal.toHex(-13));
    }
}

其实在JDK中已经封装好了十进制转十六进制的方法,它是这么写的:

Integer.toHexString(int i)

那么我们看一下JDK是怎么实现的:

/**
 * Returns a string representation of the integer argument as an
 * unsigned integer in base 16.
 *
 * <p>The unsigned integer value is the argument plus 2<sup>32</sup>
 * if the argument is negative; otherwise, it is equal to the
 * argument.  This value is converted to a string of ASCII digits
 * in hexadecimal (base&nbsp;16) with no extra leading
 * {@code 0}s.
 *
 * <p>The value of the argument can be recovered from the returned
 * string {@code s} by calling {@link
 * Integer#parseUnsignedInt(String, int)
 * Integer.parseUnsignedInt(s, 16)}.
 *
 * <p>If the unsigned magnitude is zero, it is represented by a
 * single zero character {@code '0'} ({@code '\u005Cu0030'});
 * otherwise, the first character of the representation of the
 * unsigned magnitude will not be the zero character. The
 * following characters are used as hexadecimal digits:
 *
 * <blockquote>
 *  {@code 0123456789abcdef}
 * </blockquote>
 *
 * These are the characters {@code '\u005Cu0030'} through
 * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through
 * {@code '\u005Cu0066'}. If uppercase letters are
 * desired, the {@link java.lang.String#toUpperCase()} method may
 * be called on the result:
 *
 * <blockquote>
 *  {@code Integer.toHexString(n).toUpperCase()}
 * </blockquote>
 *
 * @param   i   an integer to be converted to a string.
 * @return  the string representation of the unsigned integer value
 *          represented by the argument in hexadecimal (base&nbsp;16).
 * @see #parseUnsignedInt(String, int)
 * @see #toUnsignedString(int, int)
 * @since   JDK1.0.2
 */
public static String toHexString(int i) {
    return toUnsignedString0(i, 4);
}

然后再看下toUnsignedString0及其内部所涉及到的方法的实现:

/**
 * Convert the integer to an unsigned number.
 */
private static String toUnsignedString0(int val, int shift) {
    // assert shift > 0 && shift <=5 : "Illegal shift value";
    int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
    int chars = Math.max(((mag + (shift - 1)) / shift), 1);
    char[] buf = new char[chars];

    formatUnsignedInt(val, shift, buf, 0, chars);

    // Use special constructor which takes over "buf".
    return new String(buf, true);
}

/**
 * Returns the number of zero bits preceding the highest-order
 * ("leftmost") one-bit in the two's complement binary representation
 * of the specified {@code int} value.  Returns 32 if the
 * specified value has no one-bits in its two's complement representation,
 * in other words if it is equal to zero.
 *
 * <p>Note that this method is closely related to the logarithm base 2.
 * For all positive {@code int} values x:
 * <ul>
 * <li>floor(log<sub>2</sub>(x)) = {@code 31 - numberOfLeadingZeros(x)}
 * <li>ceil(log<sub>2</sub>(x)) = {@code 32 - numberOfLeadingZeros(x - 1)}
 * </ul>
 *
 * @param i the value whose number of leading zeros is to be computed
 * @return the number of zero bits preceding the highest-order
 *     ("leftmost") one-bit in the two's complement binary representation
 *     of the specified {@code int} value, or 32 if the value
 *     is equal to zero.
 * @since 1.5
 */
public static int numberOfLeadingZeros(int i) {
    // HD, Figure 5-6
    if (i == 0)
        return 32;
    int n = 1;
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    n -= i >>> 31;
    return n;
}

/**
 * Format a long (treated as unsigned) into a character buffer.
 * @param val the unsigned int to format
 * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary)
 * @param buf the character buffer to write to
 * @param offset the offset in the destination buffer to start at
 * @param len the number of characters to write
 * @return the lowest character  location used
 */
 static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
    int charPos = len;
    int radix = 1 << shift;
    int mask = radix - 1;
    do {
        buf[offset + --charPos] = Integer.digits[val & mask];
        val >>>= shift;
    } while (val != 0 && charPos > 0);

    return charPos;
}

/*
* Package private constructor which shares value array for speed.
* this constructor is always expected to be called with share==true.
* a separate constructor is needed because we already have a public
* String(char[]) constructor that makes a copy of the given char[].
*/
String(char[] value, boolean share) {
    // assert share : "unshared not supported";
    this.value = value;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值