Question

Is there a way in Java to use unsigned numbers like in (My)SQL?

For example: I want to use an 8-bit variable (byte) with a range like: 0 ... 256; instead of -128 ... 127.

Was it helpful?

Solution

No, Java doesn't have any unsigned primitive types apart from char (which has values 0-65535, effectively). It's a pain (particularly for byte), but that's the way it is.

Usually you either stick with the same size, and overflow into negatives for the "high" numbers, or use the wider type (e.g. short for byte) and cope with the extra memory requirements.

OTHER TIPS

You can use a class to simulate an unsigned number. For example

public class UInt8 implements Comparable<UInt8>,Serializable
   {
   public static final short MAX_VALUE=255;
   public static final short MIN_VALUE=0;
   private short storage;//internal storage in a int 16

   public UInt8(short value)
      {
      if(value<MIN_VALUE || value>MAX_VALUE) throw new IllegalArgumentException();
      this.storage=value;
      }

   public byte toByte()
      {
      //play with the shift operator ! << 
      }
  //etc...
   }

You can mostly use signed numbers as if they were unsigned. Most operations stay the same, some need to be modified. See this post.

Internally, you shouldn't be using the smaller values--just use int. As I understand it, using smaller units does nothing but slow things down. It doesn't save memory because internally Java uses the system's word size for all storage (it won't pack words).

However if you use a smaller size storage unit, it has to mask them or range check or something for every operation.

ever notice that char (any operation) char yields an int? They just really don't expect you to use these other types.

The exceptions are arrays (which I believe will get packed) and I/O where you might find using a smaller type useful... but masking will work as well.

Nope, you can't change that. If you need something larger than 127 choose something larger than a byte.

If you need to optimize your storage (e.g. large matrix) you can u can code bigger positive numbers with negatives numbers, so to save space. Then, you have to shift the number value to get the actual value when needed. For instance, I want to manipulate short positive numbers only. Here how this is possible in Java:

        short n = 32767;
        n = (short) (n + 10);
        System.out.println(n);     
        int m = (int) (n>=0?n:n+65536); 
        System.out.println(m);

So when a short integer exceeds range, it becomes negative. Yet, at least you can store this number in 16 bits, and restore its correct value by adding shift value (number of different values that can be coded). The value should be restored in a larger type (int in our case). This may not be very convenient, but I find it's so in my case.

I'm quite new to Java and to programming. Yet, I encountered the same situation recently the need of unsigned values.

It took me around two weeks to code everything I had in mind, but I'm a total noob, so you could spend much less.

The general idea is to create interface, I have named it: UnsignedNumber<Base, Shifted> and to extend Number.class whilst implementing an abstract AbstractUnsigned<Base, Shifted, Impl extends AbstractUnsigned<Base, Shifted, Impl>> class.

So, Base parameterized type represents the base type, Shifted represents actual Java type. Impl is a shortcut for Implementation of this abstract class.

Most of the time consumed boilerplate of Java 8 Lambdas and internal private classes and safety procedures. The important thing was to achieve the behavior of unsigned when mathematical operation like subtraction or negative addition spawns the zero limit: to overflow the upper signed limit backwards.

Finally, it took another couple of days to code factories and implementation sub classes.

So far I have know: UByte and MUByte UShort and MUShort UInt and MUInt ... Etc.

They are descendants of AbstractUnsigned: UByte or MUByte extend AbstractUnsigned<Byte, Short, UByte> or AbstractUnsigned<Byte, Short, MUByte> UShort or MUShort extend AbstractUnsigned<Short, Integer, UShort> or AbstractUnsigned<Short, Integer, MUShort> ...etc.

The general idea is to take unsigned upper limit as shifted (casted) type and code transposition of negative values as they were to come not from zero, but the unsigned upper limit.

UPDATE: (Thanks to Ajeans kind and polite directions)

/**
* Adds value to the current number and returns either
* new or this {@linkplain UnsignedNumber} instance based on
* {@linkplain #isImmutable()}
*
* @param value value to add to the current value
* @return new or same instance
* @see #isImmutable()
*/
public Impl plus(N value) {
    return updater(number.plus(convert(value)));
}

This is an externally accessible method of AbstractUnsigned<N, Shifted, Impl> (or as it was said before AbstractUnsigned<Base, Shifted, Impl>); Now, to the under-the-hood work:

private Impl updater(Shifted invalidated){
    if(mutable){
        number.setShifted(invalidated);
        return caster.apply(this);
    } else {
        return shiftedConstructor.apply(invalidated);
    }
}

In the above private method mutable is a private final boolean of an AbstractUnsigned. number is one of the internal private classes which takes care of transforming Base to Shifted and vice versa. What matters in correspondence with previous 'what I did last summer part' is two internal objects: caster and shiftedConstructor:

final private Function<UnsignedNumber<N, Shifted>, Impl> caster;
final private Function<Shifted, Impl> shiftedConstructor;

These are the parameterized functions to cast N (or Base) to Shifted or to create a new Impl instance if current implementation instance of the AbstractUnsigned<> is immutable.

Shifted plus(Shifted value){
    return spawnBelowZero.apply(summing.apply(shifted, value));
}

In this fragment is shown the adding method of the number object. The idea was to always use Shifted internally, because it is uncertain when the positive limits of 'original' type will be spawned. shifted is an internal parameterized field which bears the value of the whole AbstractUnsigned<>. The other two Function<> derivative objects are given below:

final private BinaryOperator<Shifted> summing;
final private UnaryOperator<Shifted> spawnBelowZero;

The former performs addition of two Shifted values. And the latter performs spawning below zero transposition.

And now an example from one of the factory boilerplates 'hell' for AbstractUnsigned<Byte, Short> specifically for the mentioned before spawnBelowZero UnaryOperator<Shifted>:

...,
         v-> v >= 0
         ? v
         : (short) (Math.abs(Byte.MIN_VALUE) + Byte.MAX_VALUE + 2 + v),
...

if Shifted v is positive nothing really happens and the original value is being returned. Otherwise: there's a need to calculate the upper limit of the Base type which is Byte and add up to that value negative v. If, let's say, v == -8 then Math.abs(Byte.MIN_VALUE) will produce 128 and Byte.MAX_VALUE will produce 127 which gives 255 + 1 to get the original upper limit which was cut of by the sign bit, as I got that, and the so desirable 256 is in the place. But the very first negative value is actually that 256 that's why +1 again or +2 in total. Finally, 255 + 2 + v which is -8 gives 255 + 2 + (-8) and 249

Or in a more visual way:

0 1 2 3 ... 245 246 247 248 249 250 251 252 253 254 255 256
                             -8  -7  -6  -5  -4  -3  -2  -1

And to finalize all that: this definitely does not ease your work or saves memory bytes, but you have a pretty much desirable behaviour when it is needed. And you can use that behaviour pretty much with any other Number.class subclasses. AbstractUnsigned being subclass of Number.class itself provides all the convenience methods and constants similar to other 'native' Number.class subclasses, including MIN_VALUE and MAX_VALUE and a lot more, for example, I coded convenience method for mutable subclasses called makeDivisibileBy(Number n) which performs the simplest operation of value - (value % n).

My initial endeavour here was to show that even a noob, such as I am, can code it. My initial endeavour when I was coding that class was to get conveniently versatile tool for constant using.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top