A defensive numeric calculation can replace a tiny denominator before division.

Program

Play the program to choose a denominator and see whether the guard is used.

raw_denominator
bounded_divide.f90
Replay: real traced execution (multi-file project)
program bounded_divide_demo
    implicit none
    real :: numerator
    real :: raw_denominator
    real :: denominator
    real :: quotient
    integer :: used_floor

    numerator = 12.0
    raw_denominator = 0.0
    denominator = raw_denominator
    used_floor = 0
    if (abs(denominator) < 1.0) then
        denominator = 1.0
        used_floor = 1
    end if
    quotient = numerator / denominator
    print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient
end program bounded_divide_demo
program bounded_divide_demo
    implicit none
    real :: numerator
    real :: raw_denominator
    real :: denominator
    real :: quotient
    integer :: used_floor

    numerator = 12.0
    raw_denominator = 2.0
    denominator = raw_denominator
    used_floor = 0
    if (abs(denominator) < 1.0) then
        denominator = 1.0
        used_floor = 1
    end if
    quotient = numerator / denominator
    print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient
end program bounded_divide_demo
program bounded_divide_demo
    implicit none
    real :: numerator
    real :: raw_denominator
    real :: denominator
    real :: quotient
    integer :: used_floor

    numerator = 12.0
    raw_denominator = 6.0
    denominator = raw_denominator
    used_floor = 0
    if (abs(denominator) < 1.0) then
        denominator = 1.0
        used_floor = 1
    end if
    quotient = numerator / denominator
    print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient
end program bounded_divide_demo
  1. numerator ← 12.0

    9numerator = 12.010raw_denominator = 0.0
    values this step12.0numerator
  2. raw_denominator ← 0.0

    9numerator = 12.010raw_denominator = 0.011denominator = raw_denominator
    values this step0.0raw_denominator
  3. denominator ← 0.0

    10raw_denominator = 0.011denominator = raw_denominator12used_floor = 0
    values this step0.0denominator
  4. used_floor ← 0

    11denominator = raw_denominator12used_floor = 013if (abs(denominator) < 1.0) then
    values this step0used_floor
  5. if (abs(denominator) < 1.0) then

    12used_floor = 013if (abs(denominator) < 1.0) then14    denominator = 1.0
    values this step.true.abs(denominator) < 1.0
  6. denominator ← 1.0

    13if (abs(denominator) < 1.0) then14    denominator = 1.015    used_floor = 1
    values this step1.0denominator
  7. used_floor ← 1

    14    denominator = 1.015    used_floor = 116end if
    values this step1used_floor
  8. quotient ← 12.0

    16end if17quotient = numerator / denominator18print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient
    values this step12.0quotient12.0numerator1.0denominator
  9. print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotien…

    17    quotient = numerator / denominator18    print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient19end program bounded_divide_demo
    output0.0 1 12.0
    values this step0.0raw_denominator1used_floor12.0quotient
  1. numerator ← 12.0

    9numerator = 12.010raw_denominator = 2.0
    values this step12.0numerator
  2. raw_denominator ← 2.0

    9numerator = 12.010raw_denominator = 2.011denominator = raw_denominator
    values this step2.0raw_denominator
  3. denominator ← 2.0

    10raw_denominator = 2.011denominator = raw_denominator12used_floor = 0
    values this step2.0denominator
  4. used_floor ← 0

    11denominator = raw_denominator12used_floor = 013if (abs(denominator) < 1.0) then
    values this step0used_floor
  5. if (abs(denominator) < 1.0) then

    12used_floor = 013if (abs(denominator) < 1.0) then14    denominator = 1.0
    values this step.false.abs(denominator) < 1.0
  6. quotient ← 6.0

    16end if17quotient = numerator / denominator18print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient
    values this step6.0quotient12.0numerator2.0denominator
  7. print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotien…

    17    quotient = numerator / denominator18    print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient19end program bounded_divide_demo
    output2.0 0 6.0
    values this step2.0raw_denominator0used_floor6.0quotient
  1. numerator ← 12.0

    9numerator = 12.010raw_denominator = 6.0
    values this step12.0numerator
  2. raw_denominator ← 6.0

    9numerator = 12.010raw_denominator = 6.011denominator = raw_denominator
    values this step6.0raw_denominator
  3. denominator ← 6.0

    10raw_denominator = 6.011denominator = raw_denominator12used_floor = 0
    values this step6.0denominator
  4. used_floor ← 0

    11denominator = raw_denominator12used_floor = 013if (abs(denominator) < 1.0) then
    values this step0used_floor
  5. if (abs(denominator) < 1.0) then

    12used_floor = 013if (abs(denominator) < 1.0) then14    denominator = 1.0
    values this step.false.abs(denominator) < 1.0
  6. quotient ← 2.0

    16end if17quotient = numerator / denominator18print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient
    values this step2.0quotient12.0numerator6.0denominator
  7. print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotien…

    17    quotient = numerator / denominator18    print '(F0.1, 1X, I0, 1X, F0.1)', raw_denominator, used_floor, quotient19end program bounded_divide_demo
    output6.0 0 2.0
    values this step6.0raw_denominator0used_floor2.0quotient
guard `abs(denominator) < 1.0` detects a risky denominator.
floor The denominator is replaced with `1.0` only when the guard fires.
audit flag `used_floor` records whether the stabilized path was used.