How can I convert an unsigned int or long represented as the signed Java equivalents to float or double in Java? I found some hints in the Google Guava libraries (Link), but I do not understand the reasoning behind the implementation. Here is the code fragment that converts an unsigned long stored in value
to float:
198 @Override
199 public float floatValue() {
200 @SuppressWarnings("cast")
201 float fValue = (float) (value & UNSIGNED_MASK);
202 if (value < 0) {
203 fValue += 0x1.0p63f;
204 }
205 return fValue;
206 }
As far as I understand, the first check is necessary to check that the value is not negative since the UNSIGNED_MASK
is Long.MAX_VALUE
. In this case, the conversion matches the Java semantics of long to float conversion. But why is a constant added, if the value is negative?
If you wish to treat to original long value
as if it's unsigned, if the signed value is negative, you have to add 2^63 to account for the sign bit.
If the original value
is already positive, you don't have to add anything, since the sign bit is 0, so only the value of the bottom 63 bits should be considered.
For example, take 1111...111111
(64 1 bits).
The signed value of this long number is -1
.
However, the unsigned value is 2^63+2^62+...+2^1+2^0
.
(float) (value & UNSIGNED_MASK)
will give you the float value of 2^62+2^61+...+2^1+2^0
.
Therefore you have to add 2^63
.