Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle unsigned shorts/ints/longs in Java

Tags:

java

groovy

I'm reading a file format that specifies some types are unsigned integers and shorts. When I read the values, I get them as a byte array. The best route to turning them into shorts/ints/longs I've seen is something like this:

ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int x = wrapped.getInt();

That looks like it could easily overflow for unsigned ints. Is there a better way to handle this scenario?

Update: I should mention that I'm using Groovy, so I absolutely don't care if I have to use a BigInteger or something like that. I just want the maximum safety on keeping the value intact.

like image 991
Mike Thomsen Avatar asked Jan 29 '23 15:01

Mike Thomsen


1 Answers

A 32bit value, signed or unsigned, can always be stored losslessly in an int*. This means that you never have to worry about putting unsigned values in signed types from a data safety point of view.

The same is true for 8bit values in bytes, 16bit values in shorts and 64bit values in longs.

Once you've read an unsigned value into the corresponding signed type, you can promote them to signed values of a larger types to more easily work with the intended value:

  • Integer.toUnsignedLong(int)
  • Short.toUnsignedInt(short)
  • Byte.toUnsignedInt(byte)

Since there's no primitive type larger than long, you can either go via BigInteger, or use the convenience methods on Long to do unsigned operations:

  • BigInteger.valueOf(Long.toUnsignedString(long))
  • Long.divideUnsigned(long,long) and friends

* This is thanks to the JVM requiring integer types to be two's complement.

like image 70
that other guy Avatar answered Feb 06 '23 15:02

that other guy