Open unserializable opened 7 years ago
Thanks for reporting. Yes, that does look weird because you see two times the value -34
. But the intention of the two constructors is quite different, in fact. as documented in the Javadoc.
uint(int)
pretends the argument int
value is really a primitive unsigned int and considers the most significant bit (holding the minus sign in 2s complement) as the 0x8000000
bit. In this case, -34
is 0xFFFFFFDE
, which is the same as the unsigned integer value 4294967262
uint(long)
takes the least significant 32 bits from the argument long
value and treats that as an unsigned integer. In this case, -34
is simply out of range.... in other words, the behaviour is expected and consistent across all types, i.e. you'll find the same duality in ubyte(byte)
vs ubyte(short)
or ushort(short)
vs. ushort(int)
or ulong(long)
vs. ulong(BigInteger)
Thanks for the quick reply, @lukaseder! My project javadocs from attached sources don't contain the references you quote. Is the jOOU version which documentation you are referring to available from Maven repositories?
But as you said the following:
uint(long)
takes the least significant 32 bits from the argumentlong
value and treats that as an unsigned integer. In this case,-34
is simply out of range
the long
handling seems even more weird, as it would be always possible to take least significant 32 bits from the long
and treat that them as unsigned integer
. The results for anything that fits into 32-bit signed integer should be identical too. Illustrating with -34
again:
String longBitString = Long.toBinaryString(-34L);
String intBitString = Integer.toBinaryString(-34);
System.out.printf("%64s%n", longBitString);
System.out.printf("%64s%n", intBitString);
which shows that the last 32 bits of long
-34
are the same as full 32 bits of int
-34
.
1111111111111111111111111111111111111111111111111111111111011110
11111111111111111111111111011110
^
One can of course do the int
cast to get the last 32-bits of the long
and then make an uint
out of it, but doesn't that kind of defeat the purpose of the uint(long)
when one needs to use uint((int)-34L)
anyway, to bypass the NumberFormatException
? Actual usage in code is not using long
constants of course, but variables of type long
.
The Javadoc is available here: https://www.jooq.org/products/jOOU/javadoc/latest ... And it should also be available from Maven Central.
Interesting comment, you're right of course. That could be a design goal. Currently, the most significant 32 bits are required to be all zero, but we don't have to require this in principle. It would lead to the obvious discussion about "clever convenience" vs. "failing early". And it would probably also complicate the ULong
type.
But I'm willing to review this change request.
Unsigned integer range handling has incorrectnesses / inconsistencies.
E.g. UInteger can be formed from integer
-34
but not from long-34
.Reported error is
Exception in thread "main" java.lang.NumberFormatException: Value is out of range : -34
for theb
definition.I would either expect both of the samples below to fail or succeed, but not act differently. What is the intent in this library? Shouldn't both these cases succeed, since -34 is a value that is representable in 32 bit signed integer?