Skip to main content
GitHub

EIA01-F. Enforce evaluation order in floating-point expressions

Programmers shall use parentheses to enforce the intended order of evaluation in floating-point expressions and avoid compiler flags that allow unsafe reassociation.

Floating-point arithmetic approximates real-number mathematics. Because of finite precision and limited range, standard mathematical rules such as associativity and distributivity laws do not generally hold. For example, (x + y) + z is not guaranteed to produce the same result as x + (y + z) due to rounding errors that depend on operand magnitudes.

In Fortran, the compiler may reorder operations to improve performance, provided that the grouping defined by parentheses is preserved. Omitting parentheses allows the compiler or hardware to reassociate terms, which can introduce unexpected rounding errors or loss of precision. Additionally, aggressive optimization flags (e.g., -Ofast ) may allow transformations that override standard-conforming protections, potentially producing numerically unstable results.

Noncompliant Code Example

In this example, the program calculates the sum of three values, where one value is orders of magnitude larger than the others. Without parentheses, the compiler is free to choose the order of evaluation. This can cause the smaller value to be effectively lost due to floating-point rounding, producing an unexpected result.

While modern compilers may sometimes produce the intended result, this behavior is not guaranteed and may vary across compilers, platforms, and optimization settings.

Non-compliant code
program association
  use iso_fortran_env, only: real32
  implicit none
  real(real32) :: a = 1.0e20_real32
  real(real32) :: b = -1.0e20_real32
  real(real32) :: c = 1.234567_real32
  real(real32) :: res

  res = a + b + c
  print *, res
end program

Compliant Solution

Using parentheses explicitly enforces the intended order of evaluation. The Fortran standard requires that expressions inside parentheses be treated as a single data entity, which prevents the compiler from reassociating terms and preserves numerical accuracy.

Compliant code
program association
  use iso_fortran_env, only: real32
  implicit none
  real(real32) :: a = 1.0e20_real32
  real(real32) :: b = -1.0e20_real32
  real(real32) :: c = 1.234567_real32
  real(real32) :: res

  res = (a + b) + c
  print *, res
end program

Noncompliant Code Example

Improper use of aggressive optimization flags can directly affect the precision of floating-point calculations. For example. GFortran's -Ofast enables optimizations that may reorder operations, ignore parentheses, or apply unsafe math transformations to improve runtime. This can invalidate numerical correctness, even in otherwise well-written code.

Non-compliant code
# Noncompliant:-Ofast may allow unsafe floating-point reassociation
gfortran -Ofast main.f90

Compliant Solution

Use compiler flags that optimize performance without compromising standard-conforming floating-point arithmetic. Flags such as -O2 or -O3 provide high optimization while preserving evaluation order and rounding behavior.

Compliant code
# Compliant: High optimization while preserving numerical accuracy
gfortran -O3 main.f90

Risk Assessment

Failure to understand the limitations of floating-point representation and its implications on the arrangement of expressions can cause unexpected arithmetic results.

RecommendationSeverityLikelihoodDetectableRepairablePriorityLevel
EIA01-FLowProbableNoNoP3L3

Bibliography

[ Fortran 2023 Interpretation Document ]Section 10.1.5.2.4 and 10.1.9