This week's book giveaways are in the Java EE and JavaScript forums.
We're giving away four copies each of The Java EE 7 Tutorial Volume 1 or Volume 2(winners choice) and jQuery UI in Action and have the authors on-line!
See this thread and this one for details.
The moose likes Beginning Java and the fly likes Convert negative integer to byte[] and back Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Convert negative integer to byte[] and back" Watch "Convert negative integer to byte[] and back" New topic
Author

Convert negative integer to byte[] and back

Mattew Force
Greenhorn

Joined: May 03, 2007
Posts: 16
Hi all,

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
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38394
    
  23
Welcome to the Ranch.

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 chars 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 ]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18745
    
  40

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


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Even prior to JDK 1.4, a DataOutputStream can do this with its writeInt() method.

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
Mattew Force
Greenhorn

Joined: May 03, 2007
Posts: 16
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 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).


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


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 an int, ie this:-
1111 1111 1111 1111 1111 1111 1101 0000.


That's what I do in the method above.

Thank you again for straightening out my ideas!
Mattew Force
Greenhorn

Joined: May 03, 2007
Posts: 16
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
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18745
    
  40

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
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Convert negative integer to byte[] and back