8

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

kellymandem
  • 1,709
  • 3
  • 17
  • 27
  • You clearly said that you want it to convert from 1 to 256...so why do you care after 256? It seems that there is an overflow issue with your code. Try to use long as types when going above 256. – ha9u63a7 Nov 04 '14 at 14:45
  • 1
    You can post questions like this on http://codereview.stackexchange.com/ – TheConstructor Nov 04 '14 at 14:48
  • 3
    @TheConstructor No, actually codereview is for working code only. This question is about solving a problem (non-working code). – Radiodef Nov 04 '14 at 16:04
  • @Radiodef ok, good to know! Thought almost working was enough. – TheConstructor Nov 04 '14 at 16:08
  • 1
    An `int` is not in decimal, by the way. – harold Nov 04 '14 at 18:53
  • @harold, could you please expound if you can on an int not being a decimal because i always thought they were the same – kellymandem Nov 04 '14 at 19:32
  • `int`s are commonly parsed from decimal strings and printed as decimal strings, but that's not a fundamental property of them. You can just as well use some base other than 10, we only use 10 because we're used to it. You could more accurate thing of an `int` as being in base 2 (that's how it will be in hardware), or base 256 because you might store it in byte-addressable memory, or at a more higher level, just one digit in base 4,294,967,295 - because when you have an `int`, you have just 1 thing (digit?) and it wraps instead of "getting longer" like a string of digits would. – harold Nov 04 '14 at 20:00

6 Answers6

10

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, ...

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • 1
    @kellymandem welcome to stackoverflow! If you find this answer useful, you may want to "accept" it, so everyone realizes your question was solved. – TheConstructor Nov 04 '14 at 15:21
  • @kellymandem To accept an answer, click on the white check mark in the upper left corner of the answer, just below the answer's rating. This also helps others struggling with similar problems find the most helpful answer :) – FreakyDan Nov 04 '14 at 16:06
3

use Integer.toHexString(i) instead of your own

Omar.Nassar
  • 379
  • 1
  • 3
  • 14
3

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);
    }
}
TheConstructor
  • 4,285
  • 1
  • 31
  • 52
2

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.

nafas
  • 5,283
  • 3
  • 29
  • 57
1

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

Adrian Totolici
  • 223
  • 2
  • 20
1

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

Community
  • 1
  • 1
stacky
  • 800
  • 6
  • 18