3

I am a beginner in Java, and have just started learning this language.

I am learning and experimenting with examples from Herbert Schildt's book to test my understanding.

My objective is to convert negative integer to hex using in-built java methods, and then back to integer (or long). However, there are two issues that I am facing:

Issue #1: as I understand from the thread hex string to decimal conversion, Java Integer parseInt error and Converting Hexadecimal String to Decimal Integer that the converted value fffffff1 is too big to fit into Integer, so I have used Long. However, when fffffff1 is converted back to Long, I don't get -15. I get garbage value = 4294967281.

Moreover, when I type-cast the result from Long to Integer, it works well. I am not sure why Long result would show garbage value and then magically I would get the right value by just typecasting the number to integer-type. I am sure I am missing something crucial here.

Issue#2: If I don't use radix (or even change it from 16 to 4) in the method Long.parseLong(), I get an exception.

Here's my code:

public class HexByte {
    public static void main(String[] args) {
        byte b = (byte) 0xf1;
        System.out.println("Integer value is:"+Integer.valueOf(b)); //you would get -15

        int i = -15;
        System.out.println("Hexadecimal value is:"+Integer.toHexString(i));

       //Let's try to convert to hex and then back to integer:
       System.out.println("Integer of Hexadecimal of -15 is:"+(int)Long.parseLong(Integer.toHexString(i),16 ));
        //type-cast to integer works well, but not sure why

        System.out.println("Integer of Hexadecimal of -15 is:"+Long.parseLong(Integer.toHexString(i),16));
        //This surprisingly throws garbage value

        System.out.println("Integer of Hexadecimal of -15 is:"+Long.parseLong(Integer.toHexString(i)));
        //doesn't work - throws an exception
    }
}

Can someone please help me? I didn't want to open duplicate threads for above issues so I have included them herewith.

Community
  • 1
  • 1
watchtower
  • 4,140
  • 14
  • 50
  • 92
  • 1
    FFFFFFF1 is not larger than an integer; if you write `System.out.println(0xFFFFFFF1)`, you'll get -15 as you would expect to. It's unclear to me why you're involving longs at all since there's really no reason to involve them. – Makoto Dec 30 '16 at 08:13
  • @Makoto - Thanks for your suggestion. I initially used integer methods, but they didn't work. Also, I believe `FFFFFFF1` would require 32 bits, but Int offers only 31 signed bits. 1 bit is left for the sign. Isn't it? I can change the question from Long to Int. The result won't change unless I am missing something crucial. – watchtower Dec 30 '16 at 08:16
  • You're missing the part where [those integral values are in two's complement](https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2). You can have 32 bits (and you would *anyway*) without needing to resort to `long`. The fact that it's signed is actually wanted by yourself due to you *expecting* the value to be negative. – Makoto Dec 30 '16 at 08:18

1 Answers1

6

Issue 1:

Negative numbers are represented using Two's Complement, which you can read more about here: wikipedia link

Basically, the left-most bit is used to determine the sign of the integer (whether it's positive or negative). A 0 means the number is positive, and a 1 means it's negative.

fffffff1 doesn't go all the way to the left, so the left-most bit when you convert that to long is a 0, which means the number is positive. When you cast it to an integer, the left bits are just dropped, and you end up somewhere in the middle of the 1s such that your leftmost digit is now a 1, so that the result is negative.

An example, with much shorter lengths for demonstration's sake:

4-bit number: 0111 -> this is positive since it starts with a 0

2-bit number using the last 2 bits of the 4-bit number: 11 -> this is negative since it starts with a 1.

Longs are like the 4-bit number in this example, and ints are like the 2-bit number. Longs have 64 bits and ints have 32 bits.


Issue 2:

If you don't specify a radix, Long.parseLong assumes base 10. You're giving it "fffffff1", and it doesn't recognize "f" as a digit in base 10 and thus throws an exception. When you specify the radix 16 then it knows "f" = 15 so there aren't any problems.

rococo
  • 2,280
  • 2
  • 22
  • 37
  • Thanks for your help. I think what's not clear to me is that if we convert `fffffff1` to decimal using calculator, we would get `4294967281` (please note that this doesn't assume 64-bit scheme, but 32-bit scheme where 4 bits are used for each hex character--I am ignoring signed bit). Thus, `fffffff1` uses 32 bits, so I am not sure whether padding of 1s (while converting from Int to Long in 2s complement format) will help at all. Do you see my point? – watchtower Dec 30 '16 at 08:27