Checker Approximation as of Julia version 2.4 (built on 23 Oct 2017)
belongs to group Basic
Identify operations that might be incorrect because of numerical approximations
Warnings generated by this checker
 ApproximateEWarning:
an approximate value of E is used instead of a constant in the libraries [ CWE197 ]  ApproximatePIWarning:
an approximate value of PI is used instead of a constant in the libraries [ CWE197 ]  CastIntComputationIntoLongWarning:
the result of an integer computation that might overflow is cast into long, with possible loss of precision [ CWE190 ]  CastIntegralComputationIntoFloatingPointWarning:
the result of an integral computation that might lose precision is cast into a floating point value [ CWE197 ]  FloatComparisonWarning:
a comparison between nonintegral values might be unreliable [ CWE197 ]
 ApproximateEWarning:

Options accepted by this checker
 none
Floating point operations are by nature approximated. This can introduce bugs when precise, mathematical properties are expected from inherently imprecise floating point computations. Moreover, computations that might lose precision or overflow, whose result is stored in a larger type, are suspicious since, by computing on the larger type from the beginning, one could avoid approximations and overflows.
Action: Use approximated comparisons (up to some epsilon) rather than exact comparisons. Use integral numbers instead of floating point values, whenever possible. Compute over integral numbers and translate into floating points only at the end, whenever possible. If a large type for the result of a computation is desired, compute from the beginning on that type instead of applying a type conversion at the end of the computation.
Examples
Consider the following program:
public class Approximation { public static void main(String[] args) { for (double d = 0.0; d != 5.0; d += 0.001) System.out.println(d); } }
This checker issues the following warning:
Approximation.java:4: [Approximation: FloatComparisonWarning ] Unsafe comparison between nonintegral numbers, that might be the approximate result of the computation at line 4
since the comparison between d
and 5.0
will always yield true, because of
approximations in the computation d += 0.001
at line 4. The while
loop will actually never terminate.
In this example, the programmer should replace d != 5.0
with d < 5.0
or
replace floating point computations with (stable and more efficient) integral computations, as follows:
for (int d = 0; d != 5000; d++) System.out.println(d / 1000.0);
Consider the following program now:
public class MillisecondsInDays { public static void main(String[] args) { int days = Integer.parseInt(args[0]); long milliseconds = days * 24 * 60 * 60 * 1000; System.out.printf("Inside %d days there are %d milliseconds", days, milliseconds); } }
This checker will issue the following warning:
MillisecondsInDays.java:4: [Approximation: CastIntComputationIntoLong ] Cast of possibly overflowing int computation into long: this might lose precision
since the computation at line 4 is performed on integers and only at the end its result
is stored into a long
. As a consequence, the extra space allowed by a long
value is not exploited and the computation would overflow if days
is larger
than 24. In this case, the programmer should have written instead:
public class MillisecondsInDays { public static void main(String[] args) { int days = Integer.parseInt(args[0]); long milliseconds = days * 24L * 60 * 60 * 1000; System.out.printf("Inside %d days there are %d milliseconds", days, milliseconds); } }
so that the whole computation is performed with long
values and the whole
space of a long
is exploitable. Overflow will only occur for very large
values of days
.