I am was having fun messing around by converting Integer to Float, Float to Long, Long to Int then I got confused by this behavior below.
When I convert a String s
representing Long.MAX_VALUE
(63 1s) I got a NumberFormatException
which was expected. because Long
is 64 bits and Integer
is 32 bits so there are extra 31 1s. (This is my guess maybe is another reason please correct me if I am wrong)
However I am not sure why I did not get a NumberFormatException
when converting Long
to Float
. Long
again is 64 bits and Float
is 32 bits just like Integer
. I know bits are interpreted differently as Float
(IEEE 754 floating-point "single format" bit layout) but what happened to all the other extra 31 bits? I am really lost here....
furthermore how do I get 9.223372E18 which is 1011111000000000000000000000000
bit string? where are those 0s from?
public static void main(String[] args){
String s = String.valueOf(Long.MAX_VALUE);
print(s); //prints 9223372036854775807
print(Long.toBinaryString(Long.MAX_VALUE)); //prints 111111111111111111111111111111111111111111111111111111111111111
//Integer.valueOf(s) this throws NumberFormatException because Long is 64 bits and Integer is 32 so s is too large to be an Integer
print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
float f = Float.valueOf(s);
int intBits = Float.floatToIntBits(f);
print(Integer.toBinaryString(intBits)); //1011111000000000000000000000000 How come? s was a String of 1s now there are 0s?
}
public static <T> void print(T arg){
System.out.println(arg);
}
First, let's confirm for you that the conversion was correct.
Long.MAX_VALUE
is 9223372036854775807 (19 digits). As you can see, the value is approximately what you printed: 9.223372E18
.
The precision of a long
is always 1
. However, the precision of a float
depends on the magnitude of the number.
In a IEEE single-precision floating point number, which float
is, there are only 24 bits of precision in the mantissa, or "fraction" part of the storage. So the actual value represented by the float
is an approximation to the actual value off Long.MAX_VALUE
.
As you've figured out, the Float.floatToIntBits
method yields different bits than the original long
bit representation.
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "single format" bit layout. Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of the floating-point number. Bits 30-23 (the bits that are selected by the mask 0x7f800000) represent the exponent. Bits 22-0 (the bits that are selected by the mask 0x007fffff) represent the significand (sometimes called the mantissa) of the floating-point number.
(snip)
Returns: the bits that represent the floating-point number.
This method doesn't convert it the value to an int
, it only gives the bit representation of the float
that happens to be stored in an int
. The value represented by this int
is not expected to be the same value as the float
.
Those zeroes are the mantissa of the floating point number. The actual conversion of long
to float
involves finding the sign for the most significant bit, finding the magnitude of the value to establish the exponent, and converting the rest of the value into the mantissa.
Because the precision of a float
at the scale of Long.MAX_VALUE
is limited, some precision is lost. The end result is that the float
value is rounded up slightly. Because Long.MAX_VALUE
is 1 short of a power of 2, the round up yields a power of 2, which shows up as all zeros in the mantissa.
You can see the precision of a floating-point value at the scale of a number with Math.ulp
(unit in last place).
Math.ulp(f)
which yields
1.09951163E12
As you can see, the difference is quite large for a float
for Long.MAX_VALUE
. (The ulp for the corresponding double
is 2048.0
. Large, but much smaller than the ulp for float
here.) But it's in line with what is expected for a value of almost 1019 -- about 7 digits of precision for a float
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With