13

I am looking for one datatype with exact capacity of 0 to 2^64 - 1. We know that Java as it is does not support 'unsigned' barring char datatype.

There is BigInteger class that allows creation of larger numbers that long datatype cannot support. But I am not sure how BigInteger class would serve my purpose. BigInteger class allows assignment through constructors only. I see the following possibility but it generates a random number.

BigInteger(int numBits, Random rnd) 
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2^numBits - 1), inclusive.

I can't see any setValue(x) kind of API that'd let me choose my own value to this BigInteger. How to implement this using BigInteger class or is there any other way of doing it? Please post code sample.

PS: The question posted by someone here does not have implementation details.

Community
  • 1
  • 1
Real Red.
  • 4,731
  • 8
  • 30
  • 44
  • 1
    Can you please clarify exactly why you need the data type and what you're trying to do with it? There may be ways to simplify the problem... – Alnitak Apr 20 '09 at 09:21
  • C++ supports such a datatype. I am interacting with C++ and thought it'd be better to have a similar datatype at Java end too rather than having to manipulate the data and convert it at C++ end. – Real Red. Apr 20 '09 at 09:26
  • For another approach ee my answer here: https://stackoverflow.com/questions/508630/java-equivalent-of-unsigned-long-long – Barry Jan 03 '21 at 02:17

8 Answers8

6

You can often use Java's signed numeric data types as if they were unsigned.

See this old answer about signed vs. unsigned in Java.

Community
  • 1
  • 1
starblue
  • 51,675
  • 14
  • 88
  • 146
3

Why not write your own wrapper and underneath use a signed long. If the user wishes to fetch the unsigned value as a BigInteger - test the sign and add 2^64 to the BigInteger.

mP.
  • 17,011
  • 10
  • 66
  • 101
2

In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2^64-1.

crownus
  • 21
  • 2
  • 2
    It would be very helpful to add a code example to this answer, or a link to some documentation. – CubeJockey Aug 21 '15 at 19:22
  • http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html - Notice the new functions... `compareUnsigned` and such... This also hints towards what Peter Lawrey was saying in his answers and comments. – Pimp Trizkit Sep 10 '15 at 19:37
2

You can create a BigInteger from a long with BigInteger.valueOf(l), where l is a long.

But if you want to work with exact 64-bits, I'd use just long.

Ingo
  • 34,949
  • 5
  • 49
  • 97
2

you may be want to create a UInt64 class, that encapsulate a BigInteger; you can also check that every operation (add, mul, etc) returns an unsigned 64 bit BigInteger; simulating the overflow maybe tricky

class UInt64 {

    private final BigInteger value;

    private UInt64(BigInteger aValue) {
         // method to enforce your class invariant: 0...2**64-1
         checkInvariantOf(aValue);
         value = aValue; 
    }

    public static UInt64 of(String value) {
         return new UInt64(new BigInteger(value));
    }

    public UInt64 add(UInt64 v) {
         return new UInt64(value.add(v.value));
    }

    ....
}
dfa
  • 107,531
  • 29
  • 184
  • 223
1

To input a uint64 into a BigInteger, you can use a constructor that takes a byte array and a signum:

public static BigInteger bigIntegerFromUInt64(long uint64) {
  if (uint64 < 0) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.putLong(uint64);
    byte[] uint64Bytes = buffer.array();

    return new BigInteger(/* signum */ 1, uint64Bytes);
  } else {
    return BigInteger.valueOf(uint64);
  }
}
weston
  • 51,132
  • 20
  • 132
  • 192
1

BigIntegers are immutable, just as you've found. You might want to look into subclassing BigInteger, and writing your own constructor that validates input, and emits a positive BigInteger in the relevant range.

To maintain the requirement that numbers are only using 64 bits, you might need to overload the various operations too, so they limit the result and return an instance of your new class rather than a new BigInteger.

This is probably quite a bit of work, but should still be far better than doing it all from scratch.

unwind
  • 364,555
  • 61
  • 449
  • 578
1

You can store values 0 to 2^64-1 in a long value.

Many operations work as expected however most of the APIs and some of the operations only work as they assume signed operations however there are workarounds.

Using BigInteger may be simpler to get your head around however. ;)

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • long supports -2^63 to (2^63)-1 as first bit is the sign bit. I want unsigned long which would then be ranging from 0 to (2^64)-1. It's not 2^(64-1) that I want. It is (2^64)-1. – Real Red. Apr 21 '09 at 06:53
  • 2
    I believe the distinction is up to you. If you use +, -, ^, &, |, <>>, ~ you will find the result is indistinguishable. If you call Long.toHexString(long) it won't print a negative number. – Peter Lawrey Apr 21 '09 at 20:40