If   f,   a,   and   b   are values with uncertainties   σf,   σa,   and   σb,   and   c   is a constant;

then if   f   is derived from   a,   b,   and   c   in the following ways,

then   σf   can be calculated as follows:

Addition/Subtraction
 If   f = a ± c,   or   f = c ± a   then   σf = σa
 If   f = a ± b   then   σf2 = σa2 + σb2
Multiplication/Division
 If   f = ca   or   f = ac       then   σf = |cσa|
 If   f = ab   or   f = a / b   then   σf2 = f2( (σa / a)2 + (σb / b)2)
Exponentiation
 If   f = ac   then   σf = |fc(σa / a)|


Caution:

This implementation of error propagation does not address issues of dependent and independent values.   It is assumed that   a   and   b   are independent and so the formula for multiplication should not be applied to   a*a   for example.   See   the talk page   for some of the implications of this issue.


Task details

 Add an uncertain number type to your language that can support addition, subtraction, multiplication, division, and exponentiation between numbers with an associated error term together with 'normal' floating point numbers without an associated error term. 
Implement enough functionality to perform the following calculations.
 Given coordinates and their errors:
x1 = 100 ± 1.1
y1 = 50 ± 1.2
x2 = 200 ± 2.2
y2 = 100 ± 2.3
 if point p1 is located at (x1, y1) and p2 is at (x2, y2); calculate the distance between the two points using the classic Pythagorean formula: 
  d = √   (x1 - x2)²   +   (y1 - y2)²    
 Print and display both    d    and its error.


References

 A Guide to Error Propagation B. Keeney, 2005.
 Propagation of uncertainty Wikipedia.


Related task

   Quaternion type


# MODE representing a uncertain number #
MODE UNCERTAIN = STRUCT( REAL v, uncertainty );
 
# add a costant and an uncertain value #
OP + = ( INT  c, UNCERTAIN u )UNCERTAIN: UNCERTAIN( v OF u + c, uncertainty OF u );
OP + = ( UNCERTAIN u, INT  c )UNCERTAIN: c + u;
OP + = ( REAL c, UNCERTAIN u )UNCERTAIN: UNCERTAIN( v OF u + c, uncertainty OF u );
OP + = ( UNCERTAIN u, REAL c )UNCERTAIN: c + u;
# add two uncertain values #
OP + = ( UNCERTAIN a, b )UNCERTAIN: UNCERTAIN( v OF a + v OF b
                                             , sqrt( ( uncertainty OF a * uncertainty OF a )
                                                   + ( uncertainty OF b * uncertainty OF b )
                                                   )
                                             );
 
# negate an uncertain value #
OP - = ( UNCERTAIN a )UNCERTAIN: ( - v OF a, uncertainty OF a );
 
# subtract an uncertain value from a constant #
OP - = ( INT  c, UNCERTAIN u )UNCERTAIN: c + - u;
OP - = ( REAL c, UNCERTAIN u )UNCERTAIN: c + - u;
# subtract a constant from an uncertain value #
OP - = ( UNCERTAIN u, INT  c )UNCERTAIN: u + - c;
OP - = ( UNCERTAIN u, REAL c )UNCERTAIN: u + - c;
# subtract two uncertain values #
OP - = ( UNCERTAIN a, b )UNCERTAIN: a + - b;
 
# multiply a constant by an uncertain value #
OP * = ( INT  c, UNCERTAIN u )UNCERTAIN: UNCERTAIN( v OF u + c, ABS( c * uncertainty OF u ) );
OP * = ( UNCERTAIN u, INT  c )UNCERTAIN: c * u;
OP * = ( REAL c, UNCERTAIN u )UNCERTAIN: UNCERTAIN( v OF u + c, ABS( c * uncertainty OF u ) );
OP * = ( UNCERTAIN u, REAL c )UNCERTAIN: c * u;
# multiply two uncertain values #
OP * = ( UNCERTAIN a, b )UNCERTAIN:
   BEGIN
       REAL av = v OF a;
       REAL bv = v OF b;
       REAL f  = av * bv;
       UNCERTAIN( f, f * sqrt( ( uncertainty OF a / av ) + ( uncertainty OF b / bv ) ) )
   END # * # ;
 
# construct the reciprocol of an uncertain value #
OP ONEOVER = ( UNCERTAIN u )UNCERTAIN: ( 1 / v OF u, uncertainty OF u );
# divide a constant by an uncertain value #
OP / = ( INT  c, UNCERTAIN u )UNCERTAIN: c * ONEOVER u;
OP / = ( REAL c, UNCERTAIN u )UNCERTAIN: c * ONEOVER u;
# divide an uncertain value by a constant #
OP / = ( UNCERTAIN u, INT  c )UNCERTAIN: u * ( 1 / c );
OP / = ( UNCERTAIN u, REAL c )UNCERTAIN: u * ( 1 / c );
# divide two uncertain values #
OP / = ( UNCERTAIN a, b )UNCERTAIN: a * ONEOVER b;
 
# exponentiation #
OP ^ = ( UNCERTAIN u, INT c )UNCERTAIN:
   BEGIN
       REAL f = v OF u ^ c;
       UNCERTAIN( f, ABS ( ( f * c * uncertainty OF u ) / v OF u ) )
   END # ^ # ;
OP ^ = ( UNCERTAIN u, REAL c )UNCERTAIN:
   BEGIN
       REAL f = v OF u ^ c;
       UNCERTAIN( f, ABS ( ( f * c * uncertainty OF u ) / v OF u ) )
   END # ^ # ;
 
# test the above operatrs by using them to find the pythagorean distance between the two sample points #
UNCERTAIN x1 = UNCERTAIN( 100, 1.1 );
UNCERTAIN y1 = UNCERTAIN(  50, 1.2 );
UNCERTAIN x2 = UNCERTAIN( 200, 2.2 );
UNCERTAIN y2 = UNCERTAIN( 100, 2.3 );
 
UNCERTAIN d  = ( ( ( x1 - x2 ) ^ 2 ) + ( y1 - y2 ) ^ 2 ) ^ 0.5;
 
print( ( "distance: ", fixed( v OF d, 0, 2 ), " +/- ", fixed( uncertainty OF d, 0, 2 ), newline ) )