• Welcome to Valhalla Legends Archive.
 

Getting around Java's lack of unsigned data

Started by Ender, December 29, 2005, 10:00 PM

Previous topic - Next topic

Ender

The problem first troubled me when I got a NegativeArraySizeException (lol) during runtime in my Java program. Basically, Java interpreted the message length word that bnet sends you in the header as being signed. It interprets everything as being signed except for chars. This may seem devastating, but there is a clever way to get around this, that doesn't take that much effort (although it is annoying to have to do it nonetheless). You basically store the data in the next highest data type, since by doing this you clear the high-order bit of the data. 

Before I give an example, I'll tell you about the drawback to this: you're using twice as much memory as necessary for storing your data! Instead of using a short (16 bits) to store a word, you have to use the 32-bit int. Yes, this sucks. Why didn't Java implement unsigned data? Don't ask me...

Example:

/**
* Takes a signed byte in and
* Returns a "functionally" unsigned short
* Which can be used as a "functionally" unsigned byte
*/
public short getUnsignedByte(byte signedByte) {     
         short s = (short) (signedByte & 0x00FF);
         return s;
}


You have to AND it with 0x00FF to convert it to an int that can then be casted into a short. If you were casting a short to an int, you'd have to AND it with 0x 00 00 FF FF.

Hope this helps someone ^_^

EDIT:

Hm, iago pwned my method. Java has a >>> operator for unsigning bytes. It shifts it x bits right and fills the left side with bit(s) of 0 to effectively unsign the data. The site that describes this operation.

So... forget my idea of storing in the next highest data type.

EDIT2:

This doesn't answer the problem of "what if there's no higher data type" as Kp pointed out in another topic (of mine). How can you compare unsigned qwords? How can you easily get the arithmetic value for an unsigned qword (with a high-order bit of 1)? I believe the way I used towards the end of the topic works, for getting arithmetic values, but it's really messy, and barely makes sense. 64-bit signed integers is Java's limit for data types. You can't use the >>> operator on a long, for instance, because that would create a 65+ bit data type, of which there is none.

MyndFyre

So... what do you do with unsigned 64-bit integers?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Ender

#2
Err... good question  ;)  ::)  ???
It's tough because any signed 64-bit integer that has a carry bit of 1, that would have negative problems, is out of Java's integer range. So to get the arithmetic value, you'd have to use floating point, doubles. You could clear the carry bit, use the java.lang.Math.pow() method to return the carry bit unsigned, and then add them together . 

double clrcarrybit = qword & (Math.pow(2, 63) - 1);  // Clear the carry bit
return clrcarrybit + Math.pow(2, 63);                         // Add it back on unsigned.


EDIT:
Hm, not sure if the above makes sense ^_^
Java really should have unsigned types...