An issue is raised when an integer value (int or long) is implicitly converted to a floating-point type (float or double) in a context where precision loss is possible.
Java allows implicit widening conversions from integer types to floating-point types. While these conversions are safe in terms of range (the floating-point type can represent larger magnitudes), they can silently lose precision.
Floating-point types use binary representation with limited precision:
float (32-bit) can only precisely represent integers up to ±16,777,216 (2^24)double (64-bit) can only precisely represent integers up to ±9,007,199,254,740,992 (2^53)When you convert larger integer values to these types, the least significant digits may be rounded, resulting in a value that differs from the original integer. This happens silently because Java permits the conversion without requiring a cast.
For example, converting the int value 16777217 to float results in 16777216.0 - the original
value cannot be represented exactly and gets rounded to the nearest representable value.
This is particularly problematic when:
Making these conversions explicit with a cast documents that you are aware of potential precision loss and helps prevent accidental data corruption.
Precision loss in conversions can lead to incorrect values being stored or processed. When working with identifiers, database keys, or financial calculations, even small rounding errors can have serious consequences.
Code that compares converted values for equality may produce unexpected results. A value converted to float and back may not equal the original integer, breaking assumptions in your logic.
Silent precision loss is hard to detect and diagnose. The code compiles without warnings, and the loss may only manifest under specific input values, making bugs intermittent and difficult to reproduce.
When converting int to float, use an explicit cast to document awareness of potential precision loss for large values
(beyond ±16,777,216).
public class DataProcessor {
public void processValue(int id) {
float floatId = id; // Noncompliant - implicit conversion may lose precision
System.out.println(floatId);
}
public float calculateRatio(int numerator, int denominator) {
float ratio = numerator / denominator; // Noncompliant - implicit conversion
return ratio;
}
}
public class DataProcessor {
public void processValue(int id) {
float floatId = (float) id; // Explicit cast shows intent
System.out.println(floatId);
}
public float calculateRatio(int numerator, int denominator) {
float ratio = (float) (numerator / denominator); // Clear conversion
return ratio;
}
}