...
In this noncompliant code example, a value of type int
is converted to the type float
because of numeric promotions (see NUM10-J. Be aware of numeric promotion behavior) float
is subtracted from a value of type int
, and the result returned as a value of type int
. Numbers of type float
have 23 mantissa bits, a sign bit, and an 8 bit exponent. The exponent allows type float
to represent a larger range than that of type int
. Nevertheless, integers whose representation requires more than 23 bits can only be represented approximately by a float
. Consequently, the result of subtracting the original from this value is -46, not zero.
Code Block | ||
---|---|---|
| ||
class WideSample { public static floatint addFloatToIntsubFloatFromInt(int op1, float op2) { return op1 +- (int)op2; } public static void main(String[] args) { floatint result = addFloatToIntsubFloatFromInt(1234567890, 1234567890); // This prints -46, and not 0 as may be expected System.out.println(result); } } |
Compliant Solution (
...
ArithmeticException
)
This compliant solution replaces the float
type double
. Numbers of type double
have 52 mantissa bits, a sign bit, and an 11 bit exponent. Consequently, integer values of type int
and narrower can be converted to double
without a loss of precision.
Code Block | ||
---|---|---|
| ||
class WideSample { public static voidint mainsubFloatFromInt(String[] args) { int big = 1234567890; int op1, float op2) throws ArithmeticException { // The significand can store at most 23 bits if ((big > 0x007fffff) || (big < -0x800000)) { throw new ArithmeticException("Insufficient precision"); } floatreturn approxop1 = big; System.out.println(big - (int)approx); // Prints zero when no precision is lost- (int)op2; } public static void main(String[] args) { int result = subFloatFromInt(1234567890, 1234567890); System.out.println(result); } } |
In this example, the subFloatFromInt()
method throws java.lang.ArithmeticException
.
Compliant Solution (
...
wider type)
This compliant solution replaces the float
type double
. Numbers of type float
The most significant bit of a float or double is its sign bit. The mantissa occupies the 23 least significant bits of a float and the 52 least significant bits of a double. The exponent, 8 bits in a float and 11 bits in a double, sits between the sign and mantissa. . The exponent allows type float
to represent a larger range than that of type int
. Nevertheless, integers whose representation requires more than 23 bits can only be represented approximately by a float
double
have 52 mantissa bits, a sign bit, and an 11 bit exponent. Consequently, integer values of type int
and narrower can be converted to double
without a loss of precision.
Code Block | ||
---|---|---|
| ||
class WideSample { public static voidint main(String[] argssubDoubleFromInt(int op1, double op2) { intreturn bigop1 = 1234567890- (int)op2; // The significand can store at most 23 bits} public static ifvoid main((big > 0x007fffff) || (big < -0x800000)String[] args) { int result throw= new ArithmeticException("Insufficient precision"subDoubleFromInt(1234567890, 1234567890); } // Works float approx = big;as expected System.out.println(big - (int)approx); // Prints zero when no precision is lostresult); } } |
Risk Assessment
Casting integer values to floating-point types whose mantissa has fewer bits than the original integer value will lose precision.
...