How to Use the Unsigned Integer in Java 8 and Java 9

How to use the unsigned Integer in Java 8 and Java 9?

Per the documentation you posted, and this blog post - there's no difference when declaring the primitive between an unsigned int/long and a signed one. The "new support" is the addition of the static methods in the Integer and Long classes, e.g. Integer.divideUnsigned. If you're not using those methods, your "unsigned" long above 2^63-1 is just a plain old long with a negative value.

From a quick skim, it doesn't look like there's a way to declare integer constants in the range outside of +/- 2^31-1, or +/- 2^63-1 for longs. You would have to manually compute the negative value corresponding to your out-of-range positive value.

Declaring an unsigned int in Java

Java does not have a datatype for unsigned integers.

You can define a long instead of an int if you need to store large values.

You can also use a signed integer as if it were unsigned. The benefit of two's complement representation is that most operations (such as addition, subtraction, multiplication, and left shift) are identical on a binary level for signed and unsigned integers. A few operations (division, right shift, comparison, and casting), however, are different. As of Java SE 8, new methods in the Integer class allow you to fully use the int data type to perform unsigned arithmetic:

In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2^32-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.

Note that int variables are still signed when declared but unsigned arithmetic is now possible by using those methods in the Integer class.

Unsigned int (primitive) and Integer (Object) usage in Java

But when I tried this out, my compiler is complaining that the value I'm using is too large, 2^31.

You have an error because the literal 2147483648 is syntactically invalid.


How exactly do I use an int/Integer to store unsigned value, such as 2^31?

You can still perform unsigned arithmetic using the new methods of the Integer class, just don't use invalid literals:

int n = 2147483647 + 1;  // 2^31

System.out.println(Integer.toUnsignedString(n)); // treat int as unsigned
System.out.println(Integer.toString(n)); // treat int as signed

2147483648
-2147483648

What I'm understanding from this quote is that I can now store up to 2^32-1 as an int as long as I use the Integer wrapper object rather than the int primitive data type.

You can store the unsigned int using the primitive type int, but using the value as an unsigned type requires you to use the utility methods of Integer, as can be seen above.

Read binary stream containing unsigned numbers

You can use

long value = Integer.toUnsignedLong​(dataInputStream.readInt());

This is equivalent to the pre-Java 8 code

long value = dataInputStream.readInt() & 0xFFFFFFFFL;

The key point is that signed or unsigned are just different interpretations of the bit pattern, but to read the four byte quantity, readInt() is always sufficient. The operation above converts to a signed long, a datatype capable of covering all values of unsigned int.

But since the int does already hold all information, there is no need to convert it to a long immediately. The Two’s Complement used to represent the signed numbers even allows performing basic operations, i.e. +, -, and *, without differentiating between signed and unsigned numbers. For other operations, Java 8 introduced methods to perform them by interpreting the int value as unsigned:

  • Integer.divideUnsigned​(…)
  • Integer.remainderUnsigned​(…)
  • Integer.compareUnsigned​(…)
  • Integer.toUnsignedString​(…)

A practical example, I encountered, is parsing class files. These files have sized encoded as unsigned int at some place, but with most standard Java APIs, class files are delivered as byte array or ByteBuffer instances, which can not contain more than 2³¹ bytes. So dealing with larger numbers is an unnecessary complication for something that can’t be correct anyway, as a class file containing such a large size specification must be truncated.

So the code to handle this looks basically like:

int size = input.readInt();
if(Integer.compareUnsigned(size, Integer.MAX_VALUE)>0) throw new IllegalArgumentException(
"truncated class file (attribute size "+Integer.toUnsignedString(size)+')');
// just use the int value

or without Java 8 features

(even simpler, as long as the reader understands the Two’s Complement):

int size = input.readInt();
if(size < 0) throw new IllegalArgumentException(
"truncated class file (attribute size "+(size&0xFFFFFFFFL)+')');
// just use the int value

(see also this answer)

Ideas to deal with unsigned integers in Java 8

EDIT: As of July 2016, the Checker Framework ships with much or all of what you are asking for: the Signedness Checker, which verifies consistent use of signed vs. unsigned values. From the manual:

The Signedness Checker guarantees that signed and unsigned values are not mixed together in a computation. In addition, it prohibits meaningless operations, such as division on an unsigned value.

(Hat tip to @MAGx2 for noticing that this answer was out of date.)


Older answer follows:

I suggest that you look into the Checker Framework. It enables you to define your own type qualifier annotations such as @Unsigned, and then to check at compile time that your code is type-correct with respect to these annotations. If it issues no warnings, then you have a guarantee that your code doesn't mix signed and unsigned values.

The Checker Framework ships with 20 type-checkers, but not one for unsigned arithmetic. You would need to write your own type-checker. This should be relatively straightforward since the type-checker would need few special rules: you just don't want to mix signed and unsigned values.

For a list of JDK methods that need library annotations, see
http://hg.openjdk.java.net/jdk8/tl/jdk/rev/71200c517524

How to do unsigned integer left shift bit operation in Java 1.8 that matches C#?

The reason is that long in Java can hold a larger number than uint in C# can. uint is limited to 4,294,967,295 (0xFFFFFFFF) whereas Java's long can hold up to 9,223,372,036,854,775,807.

Taking your example of 1265601397L << 2:

  • The C# result is 767438292
  • The Java result is 5062405588 (0x12DBE2DD4)
  • If we use a mask of 0xFFFFFFFF, then we get 0x2DBE2DD4, which equals 767438292

Therefore the solution is to use the bitwise AND operator (&) to apply the mask and get the C# int-equivalent value:

int shiftAmount = 2;
long[] tbl = { 1023326899L, 1265601397L, 3234840308L, 1673932182L };
long[] tblShift = new long[4];
for (int x = 0; x < tbl.length; ++x) {
tblShift[x] = (tbl[x] << shiftAmount) & 0xFFFFFFFFL;
}
  • Try it online (Java)
  • Fiddle of your C# code

Results:
































InputC# outputJava output
102332689940933075964093307596
1265601397767438292767438292
32348403085445934454459344
167393218224007614322400761432

Why DataInput interface in Java doesn't have readUnsignedInt method

DataInput/DataOutput has a method for each of the primitives and String.

unsigned int is not a primitive but you can do the following since it was added.

long a = dis.readInt() & 0xFFFF_FFFFL;

dos.writeInt((int) a);

Why this interface doesn't have a readUnsignedInt method that would return long?

I assume the original designers didn't think you need one or they would have added an unsigned int type.

Is there any particular reason?

There is so many things you could add (and in my library I have added because I think they are useful) but the designers seemed to believe less is more.

Best way to convert a signed integer to an unsigned long?

Something like this?

int x = -1;
long y = x & 0x00000000ffffffffL;

Or am I missing something?

public static long getUnsignedInt(int x) {
return x & 0x00000000ffffffffL;
}


Related Topics



Leave a reply



Submit