Well, first off, thank you both for your help!
So, I wrote this little program to test cancellation when subtracting two nearly equal values.
Code: Select all
// Both delta0 and delta1 suffer from rounding
// errors because they're not representable in IEEE-754
float delta0 = 0.432343547394f;
float delta1 = 0.432343587394f;
// Relative errors from both delta0 and delta1
// are bounded by machine epsilon
float delta0_rel_error = FLT_EPSILON;
float delta1_rel_error = FLT_EPSILON;
float add = delta1 + delta0;
float sub = delta1 - delta0;
float mul = delta1 * delta0;
float add_rel_error = ( fabs( delta0 * delta0_rel_error ) + fabs( delta1 * delta1_rel_error ) ) / ( fabs( add ) ) + FLT_EPSILON;
float sub_rel_error = ( fabs( delta0 * delta0_rel_error ) + fabs( delta1 * delta1_rel_error ) ) / ( fabs( sub ) ) + FLT_EPSILON;
float mul_rel_error = fabs( delta0_rel_error ) + fabs( delta1_rel_error ) + FLT_EPSILON;
The results are:
add = 0.86468714475631714;
sub = 5.96046644775390625e-8;
mul = 0.18692097067832947;
add_rel_error = 2.384185791015625e-7;
sub_rel_error = 1.7293744087219238;
mul_rel_error = 3.5763786865234375e-7;
Using exact arithmetic sub would be 4e-8 but with floating-point arithmetic it is quite far from it ( see above ). So, I guess that this turned out to be a catastrophic cancellation situation because both results ( from floating-point and exact arithmetic ) don't have any digits in common, therefore, the relative error is huge ( see above ), am I right ?
Thanks!