Like the subject says. Is there a way to convert negative integers (32-bit) to a byte array and then back? I don't know if there is an explicit way in a computer to determine if an integer is negative or not if not assuming that some bits of the integer represents the sign.

I have only managed to convert an integer to a byte array (and back again) with positive integers.

For example when I convert -48 to a byte[] and then try to convert it back I get 208 instead...

Cheers,

Mattew

One of the more interesting questions I have seen recently.

Part of your problem has to do with binary number formats.

Get yourself a standard principles of computing book,

eg Alan Clements

*the Principles of Computer Hardware [3/e]*

Oxford: Oxford University Press (2000) page 175-184

(there is a 4th edition which came out in 2006).

As for signs, the four primitive types we think of as integer numbers in

Java use the same format. (Let's keep quiet about

*char*s being

unsigned numbers.) The format is called

*two's complement*and has the

advantages that an 8-bit number can actually contain 2^8 = 256 different

values. Also exactly half the range of a two's complement number is negative

and exactly half not negative. So a byte runs from -128 to 127,

a short from -32768 to 32767 and for int and long look up Integer.MIN_VALUE

or Long.MAX_VALUE etc in the API.

You will find several ways of calculating two's complement numbers; the

officially approved way is to work out the power of 2 for one bit more than

the size you are dealing with, and subtract the number from it.

So to get from 01010101 which is a

*byte*and occupies 8 bits to its

negative values, take the power of two one larger ie 2^9, and subtract your

number from it:You will find many books tell you to invert all the bits and add 00000001.Both techniques will give you exactly the same result.

What follows is not the offically approved method of calculating back from

binary to decimal, but it works.

If you try to work out what 208 is in an

*int*, it is less than 2^8 (=256),

so every bit left of bit 7 is a 0.

(Remember, an

*int*occupies 32 bits, numbered from 0 to 31.

It is usually easier to read if you group the bits in fours.)

It actually comes to

**0000 0000 0000 0000 0000 0000**1101 0000.

If you convert that

*int*to a

*byte*, you lose the more

significant 24 bits (the 0s I printed in bold above), leaving 1101 0000.

Go back to how to convert a two's complement number to decimal, you get -48.

**So**, -48 in a

*byte*, and +208 in an

*int*use the same bits.

That is why you are converting -48 to 208, and if you try casting 208 (

*int*)

to a

*byte*, (as far as I remember) you will get -48.

I think you are correctly converting your

*int*number to a

*byte*[]

array; you are converting it back into a different format.

Not sure now how to convert the -48 which is 1101 0000 as a byte to what it should be

as an

*int*, ie this:-

**1111 1111 1111 1111 1111 1111**1101 0000.

Anybody else got any better ideas?

[edit]Added line breaks for better formatting[/edit]

[ May 03, 2007: Message edited by: Campbell Ritchie ]

However, if the goal is merely to extract the individual 4 bytes from an int, or to create an int from 4 bytes, as part of an actual program in production, this may be the long way to do it. Converting an int to a byte array, and back, doesn't take bit manipulation, and it is built into the core Java libraries (as of Java 1.4).

Henry

To do it without a library, I don't think you really need to know about two's complement, or how to convert between binary and decimal. (Though those are useful background in general if you're looking at binary representations> But bit shifting operations are useful. For example, the first byte can be found by shifting the int 24 bits to the right, then masking out all but the lowest 8 bits. Whether this is the best way to approach the problem or not probably depends on the answer to Henry's question: what is the purpose of the excercise?

[ May 03, 2007: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, *Twister*

Originally posted by Campbell Ritchie:

[QB]Welcome to the Ranch.

One of the more interesting questions I have seen recently.

Hi Campbell,

Thank you ;-)

Part of your problem has to do with binary number formats.

Get yourself a standard principles of computing book,

eg Alan Clementsthe Principles of Computer Hardware [3/e]

Oxford: Oxford University Press (2000) page 175-184

(there is a 4th edition which came out in 2006).

I've actually browsed through the Clements book when I took a class in computer hardware a couple of years ago when I was pursuing my M.Sc. in computer science :-)

So I know about two-complement and how it works well, I had to remind my self how it works, and I can follow your extensive answer (thanks again) quite easily and remember how these things acually work.

This stuff is not currently in my line of field, but I wanted to remind myself about bitwise manipulation etc. and study some more about how primitives are dealt with in Java.

So, -48 in abyte, and +208 in anintuse the same bits.

That is why you are converting -48 to 208, and if you try casting 208 (int)

to abyte, (as far as I remember) you will get -48.

I think you are correctly converting yourintnumber to abyte[]

array; you are converting it back into a different format.

Aha, some bits must have been lost in translation then. Casting does work for 208 and it becomes -48 again, but it doesn't work for larger integers which don't fit into a single byte, e.g. -765 which becomes 64771 when I convert from byte[] to int and then becomes 3 when casted back to byte.

But if you take -(2^16 - 64771) you get -765 :-)

So when the MSB of a byte is one I think I must 'or' the byte with 0xFFFFFF00. I updated my code and now it seems to give me negative integers as well. Here's the method which converts a byte array to an int:

Not sure now how to convert the -48 which is 1101 0000 as a byte to what it should be

as anint, ie this:-

1111 1111 1111 1111 1111 11111101 0000.

That's what I do in the method above.

Thank you again for straightening out my ideas!

Originally posted by Henry Wong:

My questions is ... what is the purpose of this excercise? If it is to understand two's complement, or if it is a homework assignment, then by all means, what you are doing is perfectly fine. There is no better way to understand bits, than to do low level manipulation of them.

However, if the goal is merely to extract the individual 4 bytes from an int, or to create an int from 4 bytes, as part of an actual program in production, this may be the long way to do it. Converting an int to a byte array, and back, doesn't take bit manipulation, and it is built into the core Java libraries (as of Java 1.4).

Henry

I used BigInteger.valueOf(int i).toByteArray() but it gives different sized arrays, so I think using your code would be better.

Thanks!

Mattew

Not sure now how to convert the -48 which is 1101 0000 as a byte to what it should be

as an int, ie this:-

1111 1111 1111 1111 1111 1111 1101 0000.

In Two's Complement, casting a byte to an int (or to anything bigger) is done by sign extension. Meaning the sign bit is merely extended to all the new bits -- which is what you have done in your example.

IOW, all the new bits are zero for positive numbers and one for negative numbers.

Henry

Don't get me started about those stupid light bulbs. |