2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,27 +1,39 @@
If f, a, and b are values with uncertainties σ<sub>f</sub>, σ<sub>a</sub>, and σ<sub>b</sub>. and c is a constant; then if f is derived from a, b, and c in the following ways, then σ<sub>f</sub> can be calculated as follows:
If &nbsp; '''f''', &nbsp; '''a''', &nbsp; and &nbsp; '''b''' &nbsp; are values with uncertainties &nbsp; σ<sub>f</sub>, &nbsp; σ<sub>a</sub>, &nbsp; and &nbsp; σ<sub>b</sub>, &nbsp; and &nbsp; '''c''' &nbsp; is a constant;
<br>then if &nbsp; '''f''' &nbsp; is derived from &nbsp; '''a''', &nbsp; '''b''', &nbsp; and &nbsp; '''c''' &nbsp; in the following ways,
<br>then &nbsp; σ<sub>f</sub> &nbsp; can be calculated as follows:
:;Addition/Subtraction
:* If f = a &plusmn; c, or f = c &plusmn; a then '''σ<sub>f</sub> = σ<sub>a</sub>'''
:* If f = a &plusmn; b then '''σ<sub>f</sub><sup>2</sup> = σ<sub>a</sub><sup>2</sup> + σ<sub>b</sub><sup>2</sup>'''
:* If &nbsp; f = a &plusmn; c, &nbsp; or &nbsp; f = c &plusmn; a &nbsp; then &nbsp; '''σ<sub>f</sub> = σ<sub>a</sub>'''
:* If &nbsp; f = a &plusmn; b &nbsp; then &nbsp; '''σ<sub>f</sub><sup>2</sup> = σ<sub>a</sub><sup>2</sup> + σ<sub>b</sub><sup>2</sup>'''
:;Multiplication/Division
:* If f = ca or f = ac then '''σ<sub>f</sub> = |cσ<sub>a</sub>|'''
:* If f = ab or f = a / b then '''σ<sub>f</sub><sup>2</sup> = f<sup>2</sup>( (σ<sub>a</sub> / a)<sup>2</sup> + (σ<sub>b</sub> / b)<sup>2</sup>)'''
:* If &nbsp; f = ca &nbsp; or &nbsp; f = ac &nbsp; &nbsp; &nbsp; then &nbsp; '''σ<sub>f</sub> = |cσ<sub>a</sub>|'''
:* If &nbsp; f = ab &nbsp; or &nbsp; f = a / b &nbsp; then &nbsp; '''σ<sub>f</sub><sup>2</sup> = f<sup>2</sup>( (σ<sub>a</sub> / a)<sup>2</sup> + (σ<sub>b</sub> / b)<sup>2</sup>)'''
:;Exponentiation
:* If f = a<sup>c</sup> then '''σ<sub>f</sub> = |fc(σ<sub>a</sub> / a)|'''
:* If &nbsp; f = a<sup>c</sup> &nbsp; then &nbsp; '''σ<sub>f</sub> = |fc(σ<sub>a</sub> / a)|'''
Caution:
::This implementation of error propagation does not address issues of dependent and independent values. &nbsp; It is assumed that &nbsp; '''a''' &nbsp; and &nbsp; '''b''' &nbsp; are independent and so the formula for multiplication should not be applied to &nbsp; '''a*a''' &nbsp; for example. &nbsp; See &nbsp; [[Talk:Numeric_error_propagation|the talk page]] &nbsp; for some of the implications of this issue.
: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 [[Talk:Numeric_error_propagation|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. <br>Implement enough functionality to perform the following calculations.
# Given coordinates and their errors:<br>x1 = 100 &plusmn; 1.1<br>y1 = 50 &plusmn; 1.2<br>x2 = 200 &plusmn; 2.2<br>y2 = 100 &plusmn; 2.3<br> 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:<br> '''d = &radic;((x1 - x2)<sup>2</sup> + (y1 - y2)<sup>2</sup>)'''
# Print and display both '''d''' and its error.
# Given coordinates and their errors:<br>x1 = 100 &plusmn; 1.1<br>y1 = 50 &plusmn; 1.2<br>x2 = 200 &plusmn; 2.2<br>y2 = 100 &plusmn; 2.3<br> 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: <br> <big><big> d = &radic;<span style="text-decoration:overline"> &nbsp; (x1 - x2)² &nbsp; + &nbsp; (y1 - y2)² &nbsp; </span> </big></big>
# Print and display both &nbsp; <big> '''d''' </big> &nbsp; and its error.
<!-- the superscript
2 glyph [²]
had to be used instead of the
<sup>2</sup>
notation which causes the overline "text-decoration" to either overlay the superscript or it causes a "break" in the continuous overline part of the radic. Gerard Schildberger. -->
;References:
* [http://casa.colorado.edu/~benderan/teaching/astr3510/stats.pdf A Guide to Error Propagation] B. Keeney, 2005.
* [[wp:Propagation of uncertainty|Propagation of uncertainty]] Wikipedia.
;Cf.:
* [[Quaternion type]]
;Related task:
* &nbsp; [[Quaternion type]]
<br><br>

View file

@ -0,0 +1,73 @@
# 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 ) )

View file

@ -0,0 +1,44 @@
#pragma once
#include <cmath>
#include <string>
#include <sstream>
#include <iomanip>
class Approx {
public:
Approx(double _v, double _s = 0.0) : v(_v), s(_s) {}
operator std::string() const {
std::ostringstream os("");
os << std::setprecision(15) << v << " ±" << std::setprecision(15) << s << std::ends;
return os.str();
}
Approx operator +(const Approx& a) const { return Approx(v + a.v, sqrt(s * s + a.s * a.s)); }
Approx operator +(double d) const { return Approx(v + d, s); }
Approx operator -(const Approx& a) const { return Approx(v - a.v, sqrt(s * s + a.s * a.s)); }
Approx operator -(double d) const { return Approx(v - d, s); }
Approx operator *(const Approx& a) const {
const double t = v * a.v;
return Approx(v, sqrt(t * t * s * s / (v * v) + a.s * a.s / (a.v * a.v)));
}
Approx operator *(double d) const { return Approx(v * d, fabs(d * s)); }
Approx operator /(const Approx& a) const {
const double t = v / a.v;
return Approx(t, sqrt(t * t * s * s / (v * v) + a.s * a.s / (a.v * a.v)));
}
Approx operator /(double d) const { return Approx(v / d, fabs(d * s)); }
Approx pow(double d) const {
const double t = ::pow(v, d);
return Approx(t, fabs(t * d * s / v));
}
private:
double v, s;
};

View file

@ -0,0 +1,13 @@
#include <cstdlib>
#include <iostream>
#include "numeric_error.hpp"
int main(const int argc, const char* argv[]) {
const Approx x1(100, 1.1);
const Approx x2(50, 1.2);
const Approx y1(200, 2.2);
const Approx y2(100, 2.3);
std::cout << std::string(((x1 - x2).pow(2.) + (y1 - y2).pow(2.)).pow(0.5)) << std::endl; // => 111.803398874989 ±2.938366893361
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,27 @@
PROGRAM CALCULATE !A distance, with error propagation.
REAL X1, Y1, X2, Y2 !The co-ordinates.
REAL X1E,Y1E,X2E,Y2E !Their standard deviation.
DATA X1, Y1 ,X2, Y2 /100., 50., 200.,100./ !Specified
DATA X1E,Y1E,X2E,Y2E/ 1.1, 1.2, 2.2, 2.3/ !Values.
REAL DX,DY,D2,D,DXE,DYE,E !Assistants.
CHARACTER*1 C !I'm stuck with code page 437 instead of 850.
PARAMETER (C = CHAR(241)) !Thus ± does not yield this glyph on a "console" screen. CHAR(241) does.
REAL SD !This is an arithmetic statement function.
SD(X,P,S) = P*ABS(X)**(P - 1)*S !SD for X**P where SD of X is S
WRITE (6,1) X1,C,X1E,Y1,C,Y1E, !Reveal the points
1 X2,C,X2E,Y2,C,Y2E !Though one could have used an array...
1 FORMAT ("Euclidean distance between two points:"/ !A heading.
1 ("(",F5.1,A1,F3.1,",",F5.1,A1,F3.1,")")) !Thus, One point per line.
DX = (X1 - X2) !X difference.
DXE = SQRT(X1E**2 + X2E**2) !SD for DX, a simple difference.
DY = (Y1 - Y2) !Y difference.
DYE = SQRT(Y1E**2 + Y2E**2) !SD for DY, (Y1 - Y2)
D2 = DX**2 + DY**2 !The distance, squared.
DXE = SD(DX,2,DXE) !SD for DX**2
DYE = SD(DY,2,DYE) !SD for DY**2
E = SQRT(DXE**2 + DYE**2) !SD for their sum
D = SQRT(D2) !The distance!
E = SD(D2,0.5,E) !SD after the SQRT.
WRITE (6,2) D,C,E !Ahh, the relief.
2 FORMAT ("Distance",F6.1,A1,F4.2) !Sizes to fit the example.
END !Enough.

View file

@ -0,0 +1,122 @@
MODULE ERRORFLOW !Calculate with an error estimate tagging along.
INTEGER VSP,VMAX !Do so with an arithmetic stack.
PARAMETER (VMAX = 28) !Surely sufficient.
REAL STACKV(VMAX) !Holds the values.
REAL STACKE(VMAX) !And the corresponding error estimate.
INTEGER VOUT !Output file.
LOGICAL VTRACE !Perhaps progress is to be followed in detail.
DATA VSP,VOUT,VTRACE/0,0,.FALSE./ !Start with nothing.
CHARACTER*1 PM !I'm stuck with code page 437 instead of 850.
PARAMETER (PM = CHAR(241)) !Thus ± does not yield this glyph on a "console" screen. CHAR(241) does.
CONTAINS !The servants.
SUBROUTINE VINIT(OUT) !Get ready.
INTEGER OUT !Unit number for output.
VSP = 0 !My stack is empty.
VOUT = OUT !Save this rather than have extra parameters.
VTRACE = VOUT .GT. 0 !By implication.
END SUBROUTINE VINIT !Ready.
SUBROUTINE VSHOW(WOT) !Show the topmost element.
CHARACTER*(*) WOT !The caller identifies itself.
IF (VSP.LE.0) THEN !Just in case
WRITE (VOUT,1) "Empty",VSP !My stack may be empty.
ELSE !But normally, it is not.
WRITE (VOUT,1) WOT,VSP,STACKV(VSP),PM,STACKE(VSP) !Topmost.
1 FORMAT (A8,": Vstack(",I2,") =",F8.1,A1,F6.2) !Suits the example.
END IF !So much for protection.
END SUBROUTINE VSHOW !Could reveal all the stack...
SUBROUTINE VLOAD(V,E) !Load the stack.
REAL V,E !The value and its error.
IF (VSP.GE.VMAX) STOP "VLOAD: overflow!" !Oh dear.
VSP = VSP + 1 !Up one.
STACKV(VSP) = V !Place the value.
STACKE(VSP) = E !And the error.
IF (VTRACE) CALL VSHOW("vLoad")
END SUBROUTINE VLOAD !That was easy!
SUBROUTINE VADD !Add the top two elements.
IF (VSP.LE.1) STOP "VADD: underflow!" !Maybe not.
STACKV(VSP - 1) = STACKV(VSP - 1) + STACKV(VSP) !Do the deed.
STACKE(VSP - 1) = SQRT(STACKE(VSP - 1)**2 + STACKE(VSP)**2) !The errors follow.
VSP = VSP - 1 !Two values have become one.
IF (VTRACE) CALL VSHOW("vAdd")!The result.
END SUBROUTINE VADD !The variance of the sum is the sum of the variances.
SUBROUTINE VSUB !Subtract the topmost element from the one below.
IF (VSP.LE.1) STOP "VSUB: underflow!" !Perhaps not.
STACKV(VSP - 1) = STACKV(VSP - 1) - STACKV(VSP) !The topmost was the second loaded.
STACKE(VSP - 1) = SQRT(STACKE(VSP - 1)**2 + STACKE(VSP)**2) !Add the variances also.
VSP = VSP - 1 !Two values have become one.
IF (VTRACE) CALL VSHOW("vSub")!The result.
END SUBROUTINE VSUB !Could alternatively play with the signs and add...
SUBROUTINE VMUL !Multiply the top two elements.
REAL R1,R2 !Use relative errors in place of plain SD.
IF (VSP.LE.1) STOP "VMUL: underflow!" !Perhaps not.
R1 = STACKE(VSP - 1)/STACKV(VSP - 1) !The relative errors for multiply
R2 = STACKE(VSP) /STACKV(VSP) !Are treated as are variances in addition.
STACKV(VSP - 1) = STACKV(VSP - 1)*STACKV(VSP) !Perform the multiply.
VSP = VSP - 1 !Unstack, but not quite finished.
STACKE(VSP) = SQRT((R1**2 + R2**2)*STACKV(VSP)**2) ![SD/xy]² = [SD/x]² + [SD/y]²
IF (VTRACE) CALL VSHOW("vMul") !Thus SD² = [[SD/x]² + [SD/y]²]xy²
END SUBROUTINE VMUL !The square means that the error's sign is not altered.
SUBROUTINE VDIV !Divide the penultimate element by the top elements.
REAL R1,R2 !Use relative errors in place of plain SD.
IF (VSP.LE.1) STOP "VDIV: underflow!" !Perhaps not.
R1 = STACKE(VSP - 1)/STACKV(VSP - 1) !The relative errors for divide
R2 = STACKE(VSP) /STACKV(VSP) !Are treated as are variances in subtraction.
STACKV(VSP - 1) = STACKV(VSP - 1)/STACKV(VSP) !Perform the divide.
VSP = VSP - 1 !X/Y is Load X, Load Y, Divide; Y is topmost.
STACKE(VSP) = SQRT((R1**2 + R2**2)*STACKV(VSP)**2) ![SD/(x/y)]² = [SD/x]² + [SD/y]²
IF (VTRACE) CALL VSHOW("vDiv") !Thus SD² = [[SD/x]² + [SD/y]²](x/y)²
END SUBROUTINE VDIV !Worry over y ± SD spanning zero...
SUBROUTINE VSQRT !Now for some fun with the topmost element.
IF (VSP.LE.0) STOP "VSQRT: underflow!" !Maybe not.
STACKV(VSP) = SQRT(STACKV(VSP)) !Negative? Let the system complain.
STACKE(VSP) = 0.5/STACKV(VSP)*STACKE(VSP) !F(x ± s) = F(x) ± F'(x).s
IF (VTRACE) CALL VSHOW("vSqrt") !Here, F' can't be negative.
END SUBROUTINE VSQRT !No change to the pointer.
SUBROUTINE VSQUARE !Another raise-to-a-power.
STACKE(VSP) = 2*ABS(STACKV(VSP))*STACKE(VSP) !The error's sign is not to be messed with.
STACKV(VSP) = STACKV(VSP)**2 !This will never be negative.
IF (VTRACE) CALL VSHOW("vSquare") !Keep away from zero though.
END SUBROUTINE VSQUARE !Same formula as VSQRT, just a different power.
SUBROUTINE VPOW(P) !Now for the more general.
INTEGER P !Though only integer powers for this routine, so no EXP(P*LN(x)).
IF (VSP.LE.0) STOP "VPOW: underflow!" !Perhaps not.
IF (P.EQ.0) STOP "VPOW: zero power!" !No sense in this power!
STACKE(VSP) = P*ABS(STACKV(VSP))**(P - 1)*STACKE(VSP) !Negative values a worry.
STACKV(VSP) = ABS(STACKV(VSP))**P !I only want the magnitude.
IF (VTRACE) CALL VSHOW("vPower") !So, what happened?
END SUBROUTINE VPOW !Powers with fractional parts are troublesome.
END MODULE ERRORFLOW !That will do for the test problem.
PROGRAM CALCULATE !A distance, with error propagation.
USE ERRORFLOW !For the details.
REAL X1, Y1, X2, Y2 !The co-ordinates.
REAL X1E,Y1E,X2E,Y2E !Their standard deviation.
DATA X1, Y1 ,X2, Y2 /100., 50., 200.,100./ !Specified
DATA X1E,Y1E,X2E,Y2E/ 1.1, 1.2, 2.2, 2.3/ !Values.
WRITE (6,1) X1,PM,X1E,Y1,PM,Y1E, !Reveal the points
1 X2,PM,X2E,Y2,PM,Y2E !Though one could have used an array...
1 FORMAT ("Euclidean distance between two points:"/ !A heading.
1 ("(",F5.1,A1,F3.1,",",F5.1,A1,F3.1,")")) !Thus, One point per line.
Calculate SQRT[(X2 - X1)**2 + (Y2 - Y1)**2]
CALL VINIT(6) !Start my arithmetic.
CALL VLOAD(X2,X2E)
CALL VLOAD(X1,X1E)
CALL VSUB !(X2 - X1)
CALL VSQUARE !(X2 - X1)**2
CALL VLOAD(Y2,Y2E)
CALL VLOAD(Y1,Y1E)
CALL VSUB !Y2 - Y1)
CALL VSQUARE !Y2 - Y1)**2
CALL VADD !(X2 - X1)**2 + (Y2 - Y1)**2
CALL VSQRT !SQRT((X2 - X1)**2 + (Y2 - Y1)**2)
WRITE (6,2) STACKV(1),PM,STACKE(1) !Ahh, the relief.
2 FORMAT ("Distance",F6.1,A1,F4.2) !Sizes to fit the example.
END !Enough.

View file

@ -0,0 +1,9 @@
TYPE DATUM
REAL VALUE
REAL SD
END TYPE DATUM
TYPE POINT
TYPE(DATUM) X
TYPE(DATUM) Y
END TYPE POINT
TYPE(POINT) P1,P2

View file

@ -76,8 +76,8 @@ public class Approx {
public static void main(String[] args){
Approx x1 = new Approx(100, 1.1);
Approx x2 = new Approx(50, 1.2);
Approx y1 = new Approx(200, 2.2);
Approx y1 = new Approx(50, 1.2);
Approx x2 = new Approx(200, 2.2);
Approx y2 = new Approx(100, 2.3);
x1.sub(x2).pow(2).add(y1.sub(y2).pow(2)).pow(0.5);

View file

@ -0,0 +1,40 @@
import java.lang.Math.*
data class Approx(val ν: Double, val σ: Double = 0.0) {
constructor(a: Approx) : this(a.ν, a.σ)
constructor(n: Number) : this(n.toDouble(), 0.0)
override fun toString() = "$ν ±$σ"
operator infix fun plus(a: Approx) = Approx(ν + a.ν, sqrt(σ * σ + a.σ * a.σ))
operator infix fun plus(d: Double) = Approx(ν + d, σ)
operator infix fun minus(a: Approx) = Approx(ν - a.ν, sqrt(σ * σ + a.σ * a.σ))
operator infix fun minus(d: Double) = Approx(ν - d, σ)
operator infix fun times(a: Approx): Approx {
val v = ν * a.ν
return Approx(v, sqrt(v * v * σ * σ / (ν * ν) + a.σ * a.σ / (a.ν * a.ν)))
}
operator infix fun times(d: Double) = Approx(ν * d, abs(d * σ))
operator infix fun div(a: Approx): Approx {
val v = ν / a.ν
return Approx(v, sqrt(v * v * σ * σ / (ν * ν) + a.σ * a.σ / (a.ν * a.ν)))
}
operator infix fun div(d: Double) = Approx(ν / d, abs(d * σ))
fun pow(d: Double): Approx {
val v = pow(ν, d)
return Approx(v, abs(v * d * σ / ν))
}
}
fun main(args: Array<String>) {
val x1 = Approx(100.0, 1.1)
val y1 = Approx(50.0, 1.2)
val x2 = Approx(200.0, 2.2)
val y2 = Approx(100.0, 2.3)
println(((x1 - x2).pow(2.0) + (y1 - y2).pow(2.0)).pow(0.5))
}

View file

@ -0,0 +1,25 @@
/*REXX program calculates the distance between two points (2D) with error propagation. */
parse arg a b . /*obtain arguments from the CL*/
if a=='' | a=="," then a= '100±1.1, 50±1.2' /*Not given? Then use default.*/
if b=='' | b=="," then b= '200±2.2, 100±2.3' /* " " " " " */
parse var a ax ',' ay; parse var b bx ',' by /*obtain X,Y from A & B point.*/
parse var ax ax '±' axe; parse var bx bx '±' bxE /* " err " Ax and Bx.*/
parse var ay ay '±' aye; parse var by by '±' byE /* " " " Ay " By.*/
if axE=='' then axE=0; if bxE=="" then bxE=0; /*No error? Then use default.*/
if ayE=='' then ayE=0; if byE=="" then byE=0; /* " " " " " */
say ' A point (x,y)= ' ax "±" axE', ' ay "±" ayE /*display A point (with err)*/
say ' B point (x.y)= ' bx "±" bxE', ' by "±" byE /* " B " " " */
say /*blank line for the eyeballs.*/
dx=ax-bx; dxE=sqrt(axE**2 + bxE**2); xe=#(dx, 2, dxE) /*compute X distances (& err)*/
dy=ay-by; dyE=sqrt(ayE**2 + byE**2); ye=#(dy, 2, dyE) /* " Y " " " */
D=sqrt(dx**2 + dy**2) /*compute the 2D distance. */
say 'distance=' D "±" #(D**2, .5, sqrt(xE**2 + yE**2)) /*display " " " */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
#: procedure; arg x,p,e; if p=.5 then z=1/sqrt(abs(x)); else z=abs(x)**(p-1); return p*e*z
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6
numeric form; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g=g * .5'e'_ % 2
m.=9; do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
numeric digits d; return g/1

View file

@ -0,0 +1,43 @@
import java.lang.Math._
class Approx(val ν: Double, val σ: Double = 0.0) {
def this(a: Approx) = this(a.ν, a.σ)
def this(n: Number) = this(n.doubleValue(), 0.0)
override def toString = s"$ν ±$σ"
def +(a: Approx) = Approx(ν + a.ν, sqrt(σ * σ + a.σ * a.σ))
def +(d: Double) = Approx(ν + d, σ)
def -(a: Approx) = Approx(ν - a.ν, sqrt(σ * σ + a.σ * a.σ))
def -(d: Double) = Approx(ν - d, σ)
def *(a: Approx) = {
val v = ν * a.ν
Approx(v, sqrt(v * v * σ * σ / (ν * ν) + a.σ * a.σ / (a.ν * a.ν)))
}
def *(d: Double) = Approx(ν * d, abs(d * σ))
def /(a: Approx) = {
val t = ν / a.ν
Approx(t, sqrt(t * t * σ * σ / (ν * ν) + a.σ * a.σ / (a.ν * a.ν)))
}
def /(d: Double) = Approx(ν / d, abs(d * σ))
def ^(d: Double) = {
val t = pow(ν, d)
Approx(t, abs(t * d * σ / ν))
}
}
object Approx { def apply(ν: Double, σ: Double = 0.0) = new Approx(ν, σ) }
object NumericError extends App {
def (a: Approx) = a^0.5
val x1 = Approx(100.0, 1.1)
val x2 = Approx(50.0, 1.2)
val y1 = Approx(200.0, 2.2)
val y2 = Approx(100.0, 2.3)
println((((x1 - x2)^2.0) + ((y1 - y2)^2.0))) // => 111.80339887498948 ±2.938366893361004
}