kellymandem
kellymandem

Reputation: 1769

Converting from decimal to hexadecimal

I have written a java program that is supposed to convert decimals from 1 to 256 to hexadecimal but the problem comes when i try decimals above 256 after which i start getting incorrect results. Here is a my code:

public class Conversion {

public static void main(String[] args) {

    System.out.printf("%s%14s", "Decimal", "Hexadecimal");

    for(int i = 1; i <= 300; i++) {
        System.out.printf("%7d          ", i);
        decimalToHex(i);
        System.out.println();
    }

}

private static void decimalToHex(int decimal) {
    int count;
    if(decimal >= 256) {
        count = 2;
    } else {
        count = 1;
    }
    for (int i = 1; i <= count; i++) {
        if(decimal >= 256) {
            returnHex(decimal / 256);
            decimal %= 256;
        }

        if(decimal >= 16) {
            returnHex(decimal / 16);
            decimal %= 16;
        }

        returnHex(decimal);

        decimal /= 16;
    }
}

private static void returnHex(int number) {
    switch(number) {
        case 15:
            System.out.print("F");
            break;
        case 14:
            System.out.print("E");
            break;
        case 13:
            System.out.print("D");
            break;
        case 12:
            System.out.print("C");
            break;
        case 11:
            System.out.print("B");
            break;
        case 10:
            System.out.print("A");
            break;
        default:
            System.out.printf("%d", number);
            break;
    }
}

}

This is the sample of the results that i got:

254              FE
255              FF
256              100
257              111
264              199
266              1AA
271              1FF
272              1100
273              1111

Note: I have just started learning java so keep it simple if you can. Thank you

Upvotes: 8

Views: 5208

Answers (6)

TheConstructor
TheConstructor

Reputation: 4465

So Seelenvirtuose postet a good solution for numbers up to 4095. Let's go further:

The main problem (as you might allready have noticed) is, that you need to predict what the highest digit's base-value is. You had a solution checking for 256 first, than 16. Java can find the appropriate value for us:

private static void decimalToHex(int decimal) {
    // Hex is base-16; maxDigit will hold the factor by which the highest digit needs to be multiplied to get its value
    int maxDigit = 1;
    // the condition left of && is what we want, right is to notice overflow when dealing with e.g. Integer.MAX_VALUE as input
    while(maxDigit * 16 <= decimal && maxDigit > 0) {
        maxDigit *= 16;
    }
    if(maxDigit <= 0) {
        throw new IllegalArgumentException("Can not convert "+ decimal);
    }
    // The left-most digit is the highest, so we need to go from high to low
    for(int digit = maxDigit; digit > 0; digit /= 16) {
        printHex((decimal / digit) % 16);
    }
}

// as this function prints the digits let's call it "printHex"
private static void printHex(int number) {
    switch(number) {
        case 15:
            System.out.print("F");
            break;
        case 14:
            System.out.print("E");
            break;
        case 13:
            System.out.print("D");
            break;
        case 12:
            System.out.print("C");
            break;
        case 11:
            System.out.print("B");
            break;
        case 10:
            System.out.print("A");
            break;
        default:
            System.out.printf("%d", number);
            break;
    }
}

The calculation of the highest digit's base value can become expensive for high numbers and may even fail, when the number is too close to Integer.MAX_VALUE. If you do not want to compute the value of the highest decimal beforehand, you may have a look at the next function.

As again the highest digits need to get left, but we only can safely compute the lowest digit, we compute the lowest first and reverse the sequence:

private static void decimalToHex2(int decimal) {
    // We use a StringBuilder so we can generate the digits lowest first
    StringBuilder sb = new StringBuilder();
    while (decimal > 0) {
        sb.append(returnHex(decimal % 16));
        decimal = decimal / 16;
    }
    // Now we can reverse the sequence and are fine
    String hexString = sb.reverse().toString();
    System.out.print(hexString);
}

// as this function returns the digits let's call it "returnHex"
private static char returnHex(int number) {
    switch(number) {
        case 15:
            return 'F';
        case 14:
            return 'E';
        case 13:
            return 'D';
        case 12:
            return 'C';
        case 11:
            return 'B';
        case 10:
            return 'A';
        default:
            return (char) ('0' + number);
    }
}

Upvotes: 3

nafas
nafas

Reputation: 5423

Well, Firstly answer given by @Seelenvirtuose is simple and easy to understand, I just want to top that up abit. Hexidecimal base is 16, so you don't need to worry about any other number(e.g. 256), Here I simplified your two methods as follows:

private static void decimalToHex(int num) {
        String output="";
        while(num!=0){
            output=returnHex(num%16)+output;
            num=num/16;
        }
        System.out.println(output);
}

private static String returnHex(int number) {
            switch(number) {
            case 15:
                return "F";
            case 14:
                return "E";
            case 13:
                return "D";
            case 12:
                return "C";
            case 11:
               return "B";
            case 10:
                return "A";
            default:
                return ""+number;
        }
}

All I'm doing using base 16 and loop until the number is 0. this code is based on your own implementation. so easy to understand.

Upvotes: 2

stacky
stacky

Reputation: 820

Try or adapt your code with this :

class Test {
  private static final int sizeOfIntInHalfBytes = 8;
  private static final int numberOfBitsInAHalfByte = 4;
  private static final int halfByte = 0x0F;
  private static final char[] hexDigits = { 
    '0', '1', '2', '3', '4', '5', '6', '7', 
    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  };

  public static String decToHex(int dec) {
    StringBuilder hexBuilder = new StringBuilder(sizeOfIntInHalfBytes);
    hexBuilder.setLength(sizeOfIntInHalfBytes);
    for (int i = sizeOfIntInHalfBytes - 1; i >= 0; --i)
    {
      int j = dec & halfByte;
      hexBuilder.setCharAt(i, hexDigits[j]);
      dec >>= numberOfBitsInAHalfByte;
    }
    return hexBuilder.toString(); 
  }


  public static void main(String[] args) {
     int dec = 305445566;
     String hex = decToHex(dec);
     System.out.println(hex);       
  }
}

Source : https://stackoverflow.com/a/13465128/4017037

Upvotes: 1

Seelenvirtuose
Seelenvirtuose

Reputation: 20608

You simply forgot to print out the zero values in case the decimal is less than the compare value. When explicitly printing out those zeroes, you also do not need the count variable anymore:

private static void decimalToHex(int decimal) {
    if (decimal >= 256) {
        returnHex(decimal / 256);
        decimal %= 256;
    } else {
        System.out.print("0");
    }
    if (decimal >= 16) {
        returnHex(decimal / 16);
        decimal %= 16;
    } else {
        System.out.print("0");
    }
    returnHex(decimal);
    decimal /= 16;
}

Of course, this also changes the output of the small values. It prints 000, 001, ...

Upvotes: 10

Omar.Nassar
Omar.Nassar

Reputation: 379

use Integer.toHexString(i) instead of your own

Upvotes: 3

Adrian Totolici
Adrian Totolici

Reputation: 233

you should use this method for converting decimal to hexadecimal

 int i = ...
 String hex = Integer.toHexString(i);
 System.out.println("Hex value is " + hex);

you can find more details on this link

http://www.javamex.com/tutorials/conversion/decimal_hexadecimal.shtml

Upvotes: 1

Related Questions