## Checker Approximation

**belongs to group Basic**

Identify operations that might be incorrect because of numerical approximations

### Frameworks supported by this checker

`java`

up to 11`android`

up to API level 28`dotnet`

### 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 non-integral values might be unreliable [ CWE197 ]

### Options accepted by this checker

- none

### Annotations understood by this checker

`@com.juliasoft.julia.checkers.approximation.UselessIfIntegral`

### Description

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.

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 non-integral 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`

.

Consider the following program:

using System; namespace DocumentationExamples { public class Approximation { public static void Main(string[] args) { for (double d = 0.0; d != 5.0; d += 0.001) Console.WriteLine(d); int days = int.Parse(args[0]); long milliseconds = days * 24 * 60 * 60 * 1000; Console.WriteLine("Inside %d days there are %d milliseconds", days, milliseconds); } } }

This checker issues the following warning:

```
``````
```DocumentationExamples.cs:10: [Approximation: FloatComparisonWarning ] Unsafe comparison between non-integral numbers, that might be the approximate result of the computation at line 10
DocumentationExamples.cs:14: [Approximation: CastIntComputationIntoLongWarning ] Cast of possibly overflowing int computation into long: this might lose precision

since the comparison between `d`

and `5.0`

will always yield true, because of
approximations in the computation `d += 0.001`

at line 10. 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++) Console.WriteLine(d / 1000.0);

This checker will issue a CastIntComputationIntoLong warning at line 14:

since the computation at line 14 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:

int days = Convert.ToInt32(args[0]); long milliseconds = days * 24L * 60 * 60 * 1000; Console.WriteLine("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`

.