Numerical Stability
Centered Average
Summing Smaller Deltas
Centering values before summing keeps intermediate totals small while preserving the final average.
Program
Play the program to choose a different center and recover the same average.
centered_average.f90
Replay: real traced execution (multi-file project)
program centered_average_demo
implicit none
real :: readings(3)
real :: center
real :: total_delta
real :: average
integer :: i
readings = [1002.0, 998.0, 1005.0]
center = 1000.0
total_delta = 0.0
do i = 1, 3
total_delta = total_delta + (readings(i) - center)
end do
average = center + total_delta / 3.0
print '(F0.1, 1X, F0.1)', center, average
end program centered_average_demo
program centered_average_demo
implicit none
real :: readings(3)
real :: center
real :: total_delta
real :: average
integer :: i
readings = [1002.0, 998.0, 1005.0]
center = 900.0
total_delta = 0.0
do i = 1, 3
total_delta = total_delta + (readings(i) - center)
end do
average = center + total_delta / 3.0
print '(F0.1, 1X, F0.1)', center, average
end program centered_average_demo
program centered_average_demo
implicit none
real :: readings(3)
real :: center
real :: total_delta
real :: average
integer :: i
readings = [1002.0, 998.0, 1005.0]
center = 1100.0
total_delta = 0.0
do i = 1, 3
total_delta = total_delta + (readings(i) - center)
end do
average = center + total_delta / 3.0
print '(F0.1, 1X, F0.1)', center, average
end program centered_average_demo
readings ← [1002.0, 998.0, 1005.0]
9readings = [1002.0, 998.0, 1005.0]10center = 1000.0values this step[1002.0, 998.0, 1005.0]readingscenter ← 1000.0
9readings = [1002.0, 998.0, 1005.0]10center = 1000.011total_delta = 0.0values this step1000.0centertotal_delta ← 0.0
10center = 1000.011total_delta = 0.012do i = 1, 3values this step0.0total_deltai ← 1
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step1itotal_delta ← 2.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step2.0total_delta2.0readings(1) - centeri ← 2
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step2itotal_delta ← 0.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step0.0total_delta-2.0readings(2) - centeri ← 3
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step3itotal_delta ← 5.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step5.0total_delta5.0readings(3) - centeraverage ← 1001.7
14end do15average = center + total_delta / 3.016print '(F0.1, 1X, F0.1)', center, averagevalues this step1001.7average1000.0center5.0total_deltaprint '(F0.1, 1X, F0.1)', center, average
15 average = center + total_delta / 3.016 print '(F0.1, 1X, F0.1)', center, average17end program centered_average_demooutput1000.0 1001.7values this step1000.0center1001.7average
readings ← [1002.0, 998.0, 1005.0]
9readings = [1002.0, 998.0, 1005.0]10center = 900.0values this step[1002.0, 998.0, 1005.0]readingscenter ← 900.0
9readings = [1002.0, 998.0, 1005.0]10center = 900.011total_delta = 0.0values this step900.0centertotal_delta ← 0.0
10center = 900.011total_delta = 0.012do i = 1, 3values this step0.0total_deltai ← 1
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step1itotal_delta ← 102.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step102.0total_delta102.0readings(1) - centeri ← 2
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step2itotal_delta ← 200.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step200.0total_delta98.0readings(2) - centeri ← 3
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step3itotal_delta ← 305.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step305.0total_delta105.0readings(3) - centeraverage ← 1001.7
14end do15average = center + total_delta / 3.016print '(F0.1, 1X, F0.1)', center, averagevalues this step1001.7average900.0center305.0total_deltaprint '(F0.1, 1X, F0.1)', center, average
15 average = center + total_delta / 3.016 print '(F0.1, 1X, F0.1)', center, average17end program centered_average_demooutput900.0 1001.7values this step900.0center1001.7average
readings ← [1002.0, 998.0, 1005.0]
9readings = [1002.0, 998.0, 1005.0]10center = 1100.0values this step[1002.0, 998.0, 1005.0]readingscenter ← 1100.0
9readings = [1002.0, 998.0, 1005.0]10center = 1100.011total_delta = 0.0values this step1100.0centertotal_delta ← 0.0
10center = 1100.011total_delta = 0.012do i = 1, 3values this step0.0total_deltai ← 1
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step1itotal_delta ← -98.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step-98.0total_delta-98.0readings(1) - centeri ← 2
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step2itotal_delta ← -200.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step-200.0total_delta-102.0readings(2) - centeri ← 3
11total_delta = 0.012do i = 1, 313 total_delta = total_delta + (readings(i) - center)values this step3itotal_delta ← -295.0
12do i = 1, 313 total_delta = total_delta + (readings(i) - center)14end dovalues this step-295.0total_delta-95.0readings(3) - centeraverage ← 1001.7
14end do15average = center + total_delta / 3.016print '(F0.1, 1X, F0.1)', center, averagevalues this step1001.7average1100.0center-295.0total_deltaprint '(F0.1, 1X, F0.1)', center, average
15 average = center + total_delta / 3.016 print '(F0.1, 1X, F0.1)', center, average17end program centered_average_demooutput1100.0 1001.7values this step1100.0center1001.7average
centering
Each reading is converted to a delta from `center`.
small total
`total_delta` accumulates smaller values than the original readings.
reconstruct
The final average adds the center back after dividing the deltas.