I'm learning single precision and would like to understand the error propagation. According to this nice website, addition is a dangerous operation.
So I wrote a small C program to test how quickly the errors add up. I'm not entirely sure if this is a valid way of testing. If it is, I'm unsure how to interpret the result, see below.
#include <stdio.h>
#include <math.h>
#define TYPE float
#define NUM_IT 168600
void increment (TYPE base, const TYPE increment, const unsigned long num_iters) {
TYPE err;
unsigned long i;
const TYPE ref = base + increment * num_iters;
for (i=0; i < num_iters; i++ ) {
base += increment;
}
err = (base - ref)/ref;
printf("%lu\t%9f\t%9f\t%+1.9f\n", i, base, ref, err);
}
int
main()
{
int j;
printf("iters\tincVal\trefVal\trelErr\n");
for (j = 1; j < 20; j++ ) {
increment(1e-1, 1e-6, (unsigned long) (pow(2, (j-10))* NUM_IT));
}
return 0;
}
The result of executing
gcc -pedantic -Wall -Wextra -Werror -lm errorPropagation.c && ./a.out | tee float.dat | column -t
is
iters incVal refVal relErr
329 0.100328 0.100329 -0.000005347
658 0.100657 0.100658 -0.000010585
1317 0.101315 0.101317 -0.000021105
2634 0.102630 0.102634 -0.000041596
5268 0.105259 0.105268 -0.000081182
10537 0.110520 0.110537 -0.000154624
21075 0.121041 0.121075 -0.000282393
42150 0.142082 0.142150 -0.000480946
84300 0.184163 0.184300 -0.000741986
168600 0.268600 0.268600 +0.000000222 <-- *
337200 0.439439 0.437200 +0.005120996
674400 0.781117 0.774400 +0.008673230
1348800 1.437150 1.448800 -0.008041115
2697600 2.723466 2.797600 -0.026499098
5395200 5.296098 5.495200 -0.036231972
10790400 10.441361 10.890400 -0.041232508
21580800 25.463778 21.680799 +0.174485177
43161600 32.000000 43.261597 -0.260313928 <-- **
86323200 32.000000 86.423195 -0.629729033
If the test is valid
- Why does the error change sign? If
0.1
is represented as e.g.0.100000001
, shouldn't this accumulate always to the same bias, irrespective of the number of summations? - What's special about
168600
summations (see*
)? The error becomes very small. Might be a coincidence. - Which wall is being hit at
incVal = 32.00
(see**
, last two lines). I'm still well below theunsigned long
limit.
Thanks in advance for your effort.