JLS 5.1.2 states:
« A widening primitive conversion from int to float, or from long to float, or from long 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 the round to nearest rounding policy (§4.2.4). »
This can lead to surprising behavior, even though the system is behaving correctly as defined. This can also lead to bad interactions with various library APIs. For example, consider
Math.round(1L << 50)
The result is the int value 2147483647. Overload resolution chooses the most specific overload, which in this case is `int Math.round(float)`. This incurs a long=>float widening conversion of the long value 2^50, which exceeds the range of a int, resulting in Integer.MAX_VALUE. (If a cast were used to force Math.round(long) to be called, the result would be 1L << 50 which might be more in line with one's expectations.)
A javac lint warning when lossy widening conversions occur might call out some surprising cases like these.
(Example derived from Bloch and Garrod, "Java Puzzlers Return from the Grave," JFokus 2021-02-09.)
« A widening primitive conversion from int to float, or from long to float, or from long 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 the round to nearest rounding policy (§4.2.4). »
This can lead to surprising behavior, even though the system is behaving correctly as defined. This can also lead to bad interactions with various library APIs. For example, consider
Math.round(1L << 50)
The result is the int value 2147483647. Overload resolution chooses the most specific overload, which in this case is `int Math.round(float)`. This incurs a long=>float widening conversion of the long value 2^50, which exceeds the range of a int, resulting in Integer.MAX_VALUE. (If a cast were used to force Math.round(long) to be called, the result would be 1L << 50 which might be more in line with one's expectations.)
A javac lint warning when lossy widening conversions occur might call out some surprising cases like these.
(Example derived from Bloch and Garrod, "Java Puzzlers Return from the Grave," JFokus 2021-02-09.)
- links to
-
Review(master) openjdk/jdk/23718