问题
if you call the following method of Java
void processIt(long a) {
float b = a; /*do I have loss here*/
}
do I have information loss when I assign the long variable to the float variable?
The Java language Specification says that the float type is a supertype of long.
回答1:
Yes, this is possible: if only for the reason that float
has too few (typically 6-7) significant digits to deal with all possible numbers that long
can represent (19 significant digits). This is in part due to the fact that float
has only 32 bits of storage, and long
has 64 (the other part is float's storage format † ). As per the JLS:
A widening conversion of an int or a long value to float, or of a long value to double, may result in loss of precision - that is, the result may lose some of the least significant bits of the value. In this case, the resulting floating-point value will be a correctly rounded version of the integer value, using IEEE 754 round-to-nearest mode (§4.2.4).
By example:
long i = 1000000001; // 10 significant digits
float f = i;
System.out.printf(" %d %n %.1f", i, f);
This prints (with the difference highlighted):
1000000001 1000000000.0 ~ ← lost the number 1
It is worth noting this is also the case with int
to float
and long
to double
(as per that quote). In fact the only integer → floating point conversion that won't lose precision is int
to double
.
~~~~~~
† I say in part as this is also true for int
widening to float
which can also lose precision, despite both int
and float
having 32-bits. The same sample above but with int i
has the same result as printed. This is unsurprising once you consider the way that float
is structured; it uses some of the 32-bits to store the mantissa, or significand, so cannot represent all integer numbers in the same range as that of int
.
回答2:
Do I have information loss when I assign the long variable to the float variable?
Potentially, yes. That should be fairly clear from the fact that long
has 64 bits of information, whereas float
has only 32.
More specifically, as float
values get bigger, the gap between successive values becomes more than 1 - whereas with long
, the gap between successive values is always 1.
As an example:
long x = 100000000L;
float f1 = (float) x;
float f2 = (float) (x + 1);
System.out.println(f1 == f2); // true
In other words, two different long
values have the same nearest representation in float
.
This isn't just true of float
though - it can happen with double
too. In that case the numbers have to be bigger (as double
has more precision) but it's still potentially lossy.
Again, it's reasonably easy to see that it has to be lossy - even though both long
and double
are represented in 64 bits, there are obviously double
values which can't be represented as long
values (trivially, 0.5 is one such) which means there must be some long
values which aren't exactly representable as double
values.
回答3:
Yes you will, for example...
public static void main(String[] args) {
long g = 2;
g <<= 48;
g++;
System.out.println(g);
float f = (float) g;
System.out.println(f);
long a = (long) f;
System.out.println(a);
}
... prints...
562949953421313
5.6294995E14
562949953421312
来源:https://stackoverflow.com/questions/28304565/information-loss-from-long-to-float-in-java