0

A C# system is generating data and providing data to another Java system using SBE(Simple Binary Encoding) by primitiveType="uint64" (long).

In Java, when data is received as primitive long it is overflowing and in few cases leading to –ve numbers.

How to handle this situation ?

AmbGup
  • 731
  • 1
  • 9
  • 23
  • 4
    ... not sending invalid values? – Stultuske Mar 05 '19 at 10:39
  • This shouldn't be happening, as C#'s `uint64` should be analogous to Java's `long`. Can you include some data which is causing this problem? – Tim Biegeleisen Mar 05 '19 at 10:41
  • 1
    you can use BigInteger – Akash Shah Mar 05 '19 at 10:42
  • 2
    @TimBiegeleisen Presumably the difference is that `uint64` is unsigned, whereas Java's `long` is signed. So any number in the top half of `uint64`'s range will end up negative when it is interpreted as a `long`. – khelwood Mar 05 '19 at 10:42
  • If the overflow is happening because of invalid inputs then you could throw an exception if it is causing problems further down the workflow. – James Birch Mar 05 '19 at 10:44
  • 2
    unsigned or signed does not really make a difference, you're just receiving 64 bits of data which you interpret as a number. What are you using this number for? – Lino Mar 05 '19 at 10:46
  • If you do arithmetics with that number, then maybe this [question](https://stackoverflow.com/questions/9854166/declaring-an-unsigned-int-in-java) will help you – Lino Mar 05 '19 at 10:49
  • Have you looked at the `xxxUnsigned` methods of `java.lang.Long`? They may help. – biziclop Mar 05 '19 at 10:59
  • @khelwood Yes you are correct the difference is exactly that uint64 is unsigned, whereas Java's long is signed. I have to store this number in KDB database without any processing as long – AmbGup Mar 05 '19 at 11:14

1 Answers1

1

You can receive the unsigned long as long, as "long" as one does not calculate with the long. You can even display that long as unsigned using Long.toUnsignedString(n).

Otherwise store it in a BigInteger. Ideally loaded as 8 big-endian bytes.

// Some snippets, unordered, showing useful constructs.
long n = ...;
n = Long.reverseBytes();
byte[] bigendian = new byte[8];
ByteBuffer buf = ByteBuffer.wrap(bigendian); // .order(ByteOrder.LITTLE_ENDIAN);
buf.putLong(n);

// Creating a BigInteger from unsigned long's bytes, requiring big-endian order.
BigInteger num = new BigInteger(1, bigendian); // 1 = positive
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • 2
    Even if you calculate with the `long`, you can usually get away with using methods like [`Long.divideUnsigned()`](https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#divideUnsigned-long-long-). (The other basic arithmetic operations are identical in two's complement.) – biziclop Mar 05 '19 at 11:00
  • @biziclop Thanks, I almost added `divideUnsigned/remainderUnsigned` myself. I find it remarkable that numbers > 2^63 are actually used. – Joop Eggen Mar 05 '19 at 11:20