2
\$\begingroup\$

I have rolled my own Java method for converting ints to the hexadecimal Strings:

import java.util.Arrays;
import java.util.Random;

public class Main {
    
    /**
     * Converts the input integer into its textual hexadecimal representation.
     * 
     * @param a the integer to convert.
     * @return the string representing {@code a} in hexadecimal notation.
     */
    public static String intToHexString(int a) {
        StringBuilder stringBuilder = new StringBuilder(Integer.BYTES * 2);
        boolean inLeadingZeros = true;
        
        while (a != 0) {
            char digit = toHexChar(a & 0xf);
            a >>>= 4;
            
            if (inLeadingZeros) {
                if (digit != 0) {
                    inLeadingZeros = false;
                    stringBuilder.append(digit);
                }
            } else {
                stringBuilder.append(digit);
            }
        }
        
        if (inLeadingZeros) {
            return "0";
        }
        
        return stringBuilder.reverse().toString();
    }
    
    // Converts the integer digit to its textual hexadecimal representation:
    private static char toHexChar(int digit) {
        return digit >= 0 && digit < 10 ? 
                (char)(digit + '0') :
                (char)(digit - 10 + 'a');
    }
    
    private static final int ITERATIONS = 10_000_000;
    private static final int WARMUP_ITERATIONS = 10_000_000;
    
    private static void warmup() {
        System.out.println("Warming up...");
        Random random = new Random();
        
        for (int i = 0; i < WARMUP_ITERATIONS; i++) {
            int a = random.nextInt();
            intToHexString(a);
            Integer.toHexString(a);
        }
        
        System.out.println("Warming up done.");
    }
    
    private static void benchmark() {
        long seed = System.nanoTime();
        Random random = new Random(seed);
        System.out.println("Seed = " + seed);
        
        int[] inputArray = new int[ITERATIONS];
        String[] outputArray1 = new String[inputArray.length];
        String[] outputArray2 = new String[inputArray.length];
        
        for (int i = 0; i < inputArray.length; i++) {
            inputArray[i] = random.nextInt();
        }
        
        // Benchmarking intToHexString:
        long startTime = System.nanoTime();
        
        for (int i = 0; i < ITERATIONS; i++) {
            outputArray1[i] = intToHexString(inputArray[i]);
        }
        
        long endTime = System.nanoTime();
        
        System.out.println(
                "intToHexString in " + 
                        ((endTime - startTime) / 1000_000) +
                        " milliseconds.");
        
        // Benchmarking Integer.toHexString:
        startTime = System.nanoTime();
        
        for (int i = 0; i < ITERATIONS; i++) {
            outputArray2[i] = Integer.toHexString(inputArray[i]);
        }
        
        endTime = System.nanoTime();
        
        System.out.println(
                "Integer.toHexString in " + 
                        ((endTime - startTime) / 1000_000) + 
                        " milliseconds.");
        
        System.out.println("Methods agree: " + Arrays.equals(outputArray1,
                                                             outputArray2));
    }
    
    public static void main(String[] args) {
        warmup();
        benchmark();
    }
}

Sample output Warming up... Warming up done. Seed = 1290249323142300 intToHexString in 1041 milliseconds. Integer.toHexString in 562 milliseconds. Methods agree: true

Critique request

Please tell me anything that comes to mind.

\$\endgroup\$
  • 1
    \$\begingroup\$ I see that you tagged it correctly with reinventing-the-wheel, but what is wrong with Integer.toHexString()? \$\endgroup\$ – mtj Sep 17 at 11:49
  • \$\begingroup\$ @mtj Nothing, I just wanted to compare the running times of the two methods. \$\endgroup\$ – coderodde Sep 17 at 11:52
4
\$\begingroup\$
  • inLeadingZeros I find dubious; wrong name probably
  • 0x00_00_03_44 would be output as "344" whereas conventional would be a two-fold "0344" (or even interspaced as "03 44"). The reason that from left-to-right one can create a byte by two chars.
  • The exceptional case probably can be dealt with in front.
  • Error if (digit != 0) { should be if (digit != '0') { or something else is meant.
  • toHexChar still expects an int digit 0..10. So probably a semantic clash.
  • a as parameter name is unfortunate especially in English; num or n is more clear.

I am uncertain whether your code is correct by just reading it, due to the variable & if.

/**
 * Converts the given integer into its textual hexadecimal representation.
 * 
 * @param num the integer to convert.
 * @return the string representing {@code num} in hexadecimal notation.
 */
public static String intToHexString(int num ) {
    if (num == 0) {
        return "00";
    }
    
    StringBuilder stringBuilder = new StringBuilder(Integer.BYTES * 2);
    while (num != 0) {
        char digit = toHexChar(num & 0xf);
        num >>>= 4;
        stringBuilder.append(digit);

        digit = toHexChar(num & 0xf);
        num >>>= 4;
        stringBuilder.append(digit);
    }
    return stringBuilder.reverse().toString();
}

// Converts the integer digit to its textual hexadecimal representation:
private static char toHexChar(int digit) {
    return 0 <= digit && digit < 10 ? 
            (char)(digit + '0') :
            (char)(digit - 10 + 'a');
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.