IEEE Arithmetic & Numerical Precision

27.1 Floating-point realities

print *, 0.1 + 0.2 == 0.3                 ! F (rounding)
print *, abs((0.1_dp + 0.2_dp) - 0.3_dp) < 10 * epsilon(1.0_dp)   ! compare with tolerance
print *, huge(1.0), tiny(1.0), epsilon(1.0), spacing(1.0), nearest(1.0, 1.0)

27.2 ieee_arithmetic module

use, intrinsic :: ieee_arithmetic
real(dp) :: x, nan, inf
nan = ieee_value(nan, ieee_quiet_nan)
inf = ieee_value(inf, ieee_positive_inf)
print *, ieee_is_nan(nan), ieee_is_finite(inf), ieee_is_normal(1.0_dp)
call ieee_set_rounding_mode(ieee_down)
print *, ieee_class(x) == ieee_negative_denormal
print *, ieee_support_datatype(x), ieee_next_after(1.0_dp, 2.0_dp)

27.3 ieee_exceptions

use, intrinsic :: ieee_exceptions
logical :: flag
call ieee_set_flag(ieee_all, .false.)
x = 1.0_dp / 0.0_dp
call ieee_get_flag(ieee_divide_by_zero, flag)
if (flag) print *, "division by zero occurred"
call ieee_set_halting_mode(ieee_invalid, .true.)   ! trap on invalid operations

27.4 Numerical hygiene

Use real64 by default for scientific work; consider real128 (quad) for ill-conditioned problems.

Avoid subtracting nearly equal numbers (catastrophic cancellation); reorder formulas.

Sum many small numbers carefully (Kahan summation, pairwise summation).

Use hypot, log1p-style reformulations; scale to avoid overflow.

Beware -ffast-math / -Ofast (breaks IEEE semantics, NaN checks).

Mixed precision (single for bandwidth-bound parts, double accumulators) for performance.