Numeric error propagation: Difference between revisions
m
→{{header|Wren}}: Changed to Wren S/H
m (→{{header|Kotlin}}: Fixed x2-y1-swap, c/f Java/Discussion) |
m (→{{header|Wren}}: Changed to Wren S/H) |
||
(32 intermediate revisions by 17 users not shown) | |||
Line 23:
;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 ± 1.1<br>y1 = 50 ± 1.2<br>x2 = 200 ± 2.2<br>y2 = 100 ± 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
# Print and display both <big> '''d''' </big> 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:
Line 40 ⟶ 45:
Specification of a generic type Approximation.Number, providing all the operations required to solve the task ... and some more operations, for completeness.
<
type Real is digits <>;
with function Sqrt(X: Real) return Real;
Line 87 ⟶ 92:
Sigma: Real;
end record;
end Approximation;</
The implementation:
<
package body Approximation is
Line 209 ⟶ 214:
end Put;
end Approximation;</
Instantiating the package with Float operations, to compute the distance:
<
procedure Test_Approximations is
Line 229 ⟶ 234:
((X1-X2)**2 + (Y1 - Y2)**2)**0.5,
Sigma_Fore => 1);
end Test_Approximations;</
Output:
Line 236 ⟶ 241:
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
<
MODE UNCERTAIN = STRUCT( REAL v, uncertainty );
Line 308 ⟶ 313:
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 ) )</
{{out}}
<pre>
Line 316 ⟶ 321:
=={{header|C}}==
Rewrote code to make it more compact and added a nice formatting function for imprecise values so that they are printed out in a technically correct way i.e. with the symbol '±' . Output pasted after code.
<syntaxhighlight lang="c">
#include <stdlib.h>
#include <string.h>
Line 392 ⟶ 397:
return 0;
}
</syntaxhighlight>
<pre>
Line 403 ⟶ 408:
=={{header|C++}}==
numeric_error.hpp
<
#include <cmath>
Line 446 ⟶ 451:
private:
double v, s;
};</
numeric_error.cpp
<
#include <iostream>
#include "numeric_error.hpp"
Line 460 ⟶ 465:
return EXIT_SUCCESS;
}</
{{out}}
<pre>111.803398874989 ±2.938366893361</pre>
=={{header|Common Lisp}}==
<syntaxhighlight lang="lisp">(defstruct uncertain-number
(value 0 :type number)
(uncertainty 0 :type number))
(defmethod print-object ((n uncertain-number) stream)
(format stream "~,2F ± ~,2F" (uncertain-number-value n) (uncertain-number-uncertainty n)))
(defun ~+ (n1 n2)
(let* ((value1 (uncertain-number-value n1))
(value2 (uncertain-number-value n2))
(uncertainty1 (uncertain-number-uncertainty n1))
(uncertainty2 (uncertain-number-uncertainty n2))
(value (+ value1 value2))
(uncertainty (sqrt (+ (* uncertainty1 uncertainty1)
(* uncertainty2 uncertainty2)))))
(make-uncertain-number :value value :uncertainty uncertainty)))
(defun negate (n)
(make-uncertain-number :value (- (uncertain-number-value n))
:uncertainty (uncertain-number-uncertainty n)))
(defun ~- (n1 n2)
(~+ n1 (negate n2)))
(defun ~* (n1 n2)
(let* ((value1 (uncertain-number-value n1))
(value2 (uncertain-number-value n2))
(uncertainty-ratio-1 (/ (uncertain-number-uncertainty n1) value1))
(uncertainty-ratio-2 (/ (uncertain-number-uncertainty n2) value2))
(value (* value1 value2))
(uncertainty (sqrt (* value
value
(+ (* uncertainty-ratio-1 uncertainty-ratio-1)
(* uncertainty-ratio-2 uncertainty-ratio-2))))))
(make-uncertain-number :value value :uncertainty uncertainty)))
(defun inverse (n)
(make-uncertain-number :value (/ (uncertain-number-value n))
:uncertainty (uncertain-number-uncertainty n)))
(defun ~/ (n1 n2)
(~* n1 (inverse n2)))
(defun ~expt (base exp)
(let* ((base-value (uncertain-number-value base))
(uncertainty-ratio (/ (uncertain-number-uncertainty base) base-value))
(value (expt base-value exp))
(uncertainty (abs (* value exp uncertainty-ratio))))
(make-uncertain-number :value value :uncertainty uncertainty)))
(defun solve ()
(let* ((x1 (make-uncertain-number :value 100 :uncertainty 1.1))
(y1 (make-uncertain-number :value 50 :uncertainty 1.2))
(x2 (make-uncertain-number :value 200 :uncertainty 2.2))
(y2 (make-uncertain-number :value 100 :uncertainty 2.3))
(d (~expt (~+ (~expt (~- x1 x2) 2) (~expt (~- y1 y2) 2))
1/2)))
(format t "d = ~A~%" d)))</syntaxhighlight>
{{out}}
<pre>d = 111.80 ± 2.49</pre>
=={{header|D}}==
<
const struct Imprecise {
Line 565 ⟶ 632:
writefln("Point p2: (%s, %s)", p2[0], p2[1]);
writeln("Distance(p1, p2): ", distance(p1, p2));
}</
{{out}}
<pre>Point p1: (I(value=100, delta=1.1), I(value=50, delta=1.2))
Point p2: (I(value=200, delta=2.2), I(value=100, delta=2.3))
Distance(p1, p2): I(value=111.803, delta=2.48717)</pre>
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">let sqr (x : float) = x * x
let abs (x : float) = System.Math.Abs x
let pow = System.Math.Pow
type Approx (value : float, sigma : float) =
member this.value = value
member this.sigma = sigma
static member (~-) (x : Approx) = Approx (- x.value, x.sigma)
static member (%+) (x: Approx, y : float) = Approx (x.value + y, x.sigma)
static member (%+) (y : float, x : Approx) = x %+ y
static member (%+) (x : Approx, y : Approx) =
Approx (x.value + y.value, sqrt((sqr x.sigma)+(sqr y.sigma)))
static member (%-) (x: Approx, y : float) = Approx (x.value - y, x.sigma)
static member (%-) (y : float, x : Approx) = (-x) %+ y
static member (%-) (x : Approx, y : Approx) = x %+ (-y)
static member (%*) (x : Approx, y : float) = Approx (y * x.value, abs(y * x.sigma))
static member (%*) (y : float, x : Approx) = x %* y
static member (%*) (x : Approx, y : Approx) =
let v = x.value * y.value
Approx (v, v * sqrt(sqr(x.sigma/x.value))+sqr(y.sigma/y.value))
static member (%/) (x : Approx, y : Approx) =
Approx (x.value / y.value, sqrt(sqr(x.sigma/x.value))+sqr(y.sigma/y.value))
static member (%^) (x : Approx, y : float) =
if y < 0. then failwith ("Cannot raise the power with a negative number " + y.ToString())
let v = pow(x.value,y)
Approx (v, abs(v * y * x.sigma / x.value))
override this.ToString() = sprintf "%.2f ±%.2f" value sigma
[<EntryPoint>]
let main argv =
let x1 = Approx (100., 1.1)
let y1 = Approx (50., 1.2)
let x2 = Approx (200., 2.2)
let y2 = Approx (100., 2.3)
printfn "Distance: %A" ((((x1 %- x2) %^ 2.) %+ ((y1 %- y2) %^ 2.)) %^ 0.5)
0</syntaxhighlight>
{{out}}
<pre>Distance: 111.80 ±2.49</pre>
=={{header|Factor}}==
This version defines a new type, <code>imprecise</code>, and also defines a custom syntax similar to the syntax for complex numbers. It uses multi-methods to handle various combinations of scalar and compound values. The <code>multi-methods</code> vocabulary is described as experimental, but aside from a (probably intentional) clunky interface which requires the programmer to disambiguate generic word definitions, and the fact that multi-methods don't show up in the help browser properly, I had no issues with them. In some stress tests, they don't appear to suffer from speed issues.
{{works with|Factor|0.99 2019-10-06}}
<syntaxhighlight lang="factor">USING: accessors arrays fry kernel locals math math.functions
multi-methods parser prettyprint prettyprint.custom sequences ;
RENAME: GENERIC: multi-methods => MM-GENERIC:
FROM: syntax => M: ;
IN: imprecise
TUPLE: imprecise
{ value float read-only }
{ sigma float read-only } ;
C: <imprecise> imprecise
: >imprecise< ( imprecise -- value sigma )
[ value>> ] [ sigma>> ] bi ;
! Define a custom syntax for imprecise numbers.
<< SYNTAX: I{ \ } [ first2 <imprecise> ] parse-literal ; >>
M: imprecise pprint-delims drop \ I{ \ } ;
M: imprecise >pprint-sequence >imprecise< 2array ;
M: imprecise pprint* pprint-object ;
<PRIVATE
! Error functions
: f+-i ( float imprecise quot -- imprecise )
[ >imprecise< ] dip dip <imprecise> ; inline
: i+-i ( imprecise1 imprecise2 quot -- imprecise )
'[ [ value>> ] bi@ @ ]
[ [ sigma>> sq ] bi@ + sqrt <imprecise> ] 2bi ; inline
: f*/i ( float imprecise quot -- imprecise )
[ >imprecise< overd ] dip [ * abs ] 2bi* <imprecise> ;
inline
:: i*/i ( a b quot -- imprecise )
a b [ >imprecise< ] bi@ :> ( vala siga valb sigb )
vala valb quot call :> val
val sq siga sq * vala sq /f sigb sq + valb sq /f sqrt :> sig
val sig <imprecise> ; inline
PRIVATE>
MM-GENERIC: ~+ ( obj1 obj2 -- imprecise ) foldable flushable
METHOD: ~+ { float imprecise } [ + ] f+-i ;
METHOD: ~+ { imprecise float } swap ~+ ;
METHOD: ~+ { imprecise imprecise } [ + ] i+-i ;
MM-GENERIC: ~- ( obj1 obj2 -- imprecise ) foldable flushable
METHOD: ~- { float imprecise } [ - ] f+-i ;
METHOD: ~- { imprecise float } swap [ swap - ] f+-i ;
METHOD: ~- { imprecise imprecise } [ - ] i+-i ;
MM-GENERIC: ~* ( obj1 obj2 -- imprecise ) foldable flushable
METHOD: ~* { float imprecise } [ * ] f*/i ;
METHOD: ~* { imprecise float } swap ~* ;
METHOD: ~* { imprecise imprecise } [ * ] i*/i ;
MM-GENERIC: ~/ ( obj1 obj2 -- imprecise ) foldable flushable
METHOD: ~/ { float imprecise } [ /f ] f*/i ;
METHOD: ~/ { imprecise float } swap [ swap /f ] f*/i ;
METHOD: ~/ { imprecise imprecise } [ /f ] i*/i ;
:: ~^ ( a x -- imprecise )
a >imprecise< :> ( vala siga )
vala x ^ >rect drop :> val
val x * siga vala /f * abs :> sig
val sig <imprecise> ; foldable flushable
<PRIVATE
: imprecise-demo ( -- )
I{ 100 1.1 } I{ 200 2.2 } ~- 2. ~^
I{ 50 1.2 } I{ 100 2.3 } ~- 2. ~^ ~+ 0.5 ~^ . ;
PRIVATE>
MAIN: imprecise-demo</syntaxhighlight>
{{out}}
<pre>
I{ 111.8033988749895 2.487167063146342 }
</pre>
The following version is more idiomatic for Factor, where the convention for simple numeric types is to define regular words that work on sequences. For examples of this, check out words like <code>v+n</code> in the <code>math.vectors</code> vocabulary or <code>q+</code> in <code>math.quaternions</code>. Since these words perform no dispatch, all three forms are defined: <code>v-n</code> for subtracting a scalar from a vector, <code>n-v</code> for subtracting a vector from a scalar, and <code>v-</code> for subtracting two vectors. This convention has been used in the following example.
{{works with|Factor|0.99 2019-10-06}}
<syntaxhighlight lang="factor">USING: arrays kernel locals math math.functions math.vectors
prettyprint sequences sequences.extras ;
IN: uncertain
<PRIVATE
: ubi* ( x y p q -- u )
[ [ first2 ] bi@ swapd ] 2dip 2bi* 2array ; inline
: err+ ( x y -- z ) [ sq ] bi@ + sqrt ;
:: (u*) ( u1 u2 quot -- u )
u1 u2 [ first2 ] bi@ :> ( v1 s1 v2 s2 )
v1 v2 quot call :> val
s1 v1 /f sq s2 v2 /f sq + val sq * sqrt :> sig
val sig 2array ; inline
PRIVATE>
: u+n ( u n -- u ) 0 2array v+ ;
: n+u ( n u -- u ) swap u+n ;
: u-n ( u n -- u ) 0 2array v- ;
: n-u ( n u -- u ) [ 0 2array ] dip v- ;
: u+ ( u u -- u ) [ + ] [ err+ ] ubi* ;
: u- ( u u -- u ) [ - ] [ err+ ] ubi* ;
: u*n ( u n -- u ) dup 2array [ * ] [ * abs ] ubi* ;
: n*u ( n u -- u ) swap u*n ;
: u/n ( u n -- u ) dup 2array [ /f ] [ * abs ] ubi* ;
: n/u ( n u -- u ) [ dup 2array ] dip [ /f ] [ * abs ] ubi* ;
: u* ( u u -- u ) [ * ] (u*) ;
: u/ ( u u -- u ) [ /f ] (u*) ;
:: u^n ( u n -- u )
u first2 :> ( v1 s1 )
v1 n ^ >rect drop :> val
val n * s1 v1 /f * abs :> sig
val sig 2array ;
<PRIVATE
: uncertain-demo ( -- )
{ 100 1.1 } { 200 2.2 } u- 2.0 u^n
{ 50 1.2 } { 100 2.3 } u- 2.0 u^n u+ 0.5 u^n . ;
PRIVATE>
MAIN: uncertain-demo</syntaxhighlight>
{{out}}
<pre>
{ 111.8033988749895 2.487167063146342 }
</pre>
=={{header|Fortran}}==
===Direct calculation===
Following the propagation of error estimates through a computation is a nightmare of convoluted formulae wherein mistakes are easily made. The basic method is to derive the formulae according to the standard rules while carrying forward the calculation by hand with the utmost caution. A computer can perform the calculations, but the real problem is in ensuring that it performs the correct calculations, not some misbegotten confusion... So, rather than attempt to "optimise" the calculation, the objective is to reduce brain strain by producing code whose ''checkability'' is optimised instead, somewhat as follows: <
REAL X1, Y1, X2, Y2 !The co-ordinates.
REAL X1E,Y1E,X2E,Y2E !Their standard deviation.
Line 599 ⟶ 852:
WRITE (6,2) D,C,E !Ahh, the relief.
2 FORMAT ("Distance",F6.1,A1,F4.2) !Sizes to fit the example.
END !Enough.</
This is old-style Fortran, except for the CHARACTER variable caused by problems with character codes and their screen glyphs. As can be seen, the formulae invite mistakes which is why there is no attempt to produce a single arithmetic expression for the result and its error estimate. Further, rather than attempt to emplace appropriate instances of the formula for a value raised to some power (squaring, and square root), risking all manner of misthinks, a function to do so is prepared, here using Fortran's "arithmetic statement function" protocol, expressly intended for such situations. And the results are...
<pre>
Line 612 ⟶ 865:
===More general===
Rather than agonise over devising adjoint formulae for the error propagation through some calculation, one can perform the desired calculation via routines that will carry along the error term, as follows:<
INTEGER VSP,VMAX !Do so with an arithmetic stack.
PARAMETER (VMAX = 28) !Surely sufficient.
Line 634 ⟶ 887:
WRITE (VOUT,1) "Empty",VSP !My stack may be empty.
ELSE !But normally, it is not.
1 FORMAT (A8,": Vstack(",I2,") =",F8.1,A1,F6.2,F9.1,"%") !Suits the example.
ELSE !Avoiding a divide-by-zero is polite.
WRITE (VOUT,1) WOT,VSP,STACKV(VSP),PM,STACKE(VSP), !Possibly, a surprise, still.
1 STACKE(VSP)/STACKV(VSP)*100 !The relative error may well be interesting.
END IF !The pearls have been cast.
END IF !So much for protection.
END SUBROUTINE VSHOW !Could reveal all the stack...
Line 733 ⟶ 991:
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.</
This is closer to the idea of extending the language to supply additional facilities. At the cost of hand-compiling the arithmetic expression into a sequence of pseudo-machine code subroutines, it is apparent that the mind-tangling associated error formulae need no longer be worried over. The various arithmetic subroutines have to be coded correctly with careful attention to the V or E statements in fact being for the V and E terms (cut&paste followed by inadequate adjustment the culprit here: such mistakes are less likely when using a card punch because copying is more troublesome), but this is a straightforward matter of checking. And indeed the VPOW(2) routine has the same effect as VSQUARE. Output:
<pre>
Line 739 ⟶ 997:
(100.0±1.1, 50.0±1.2)
(200.0±2.2,100.0±2.3)
vLoad: Vstack( 1) = 200.0± 2.20 1.1%
vLoad: Vstack( 2) = 100.0± 1.10 1.1%
vSub: Vstack( 1) = 100.0± 2.46 2.5%
vSquare: Vstack( 1) = 10000.0±491.93 4.9%
vLoad: Vstack( 2) = 100.0± 2.30 2.3%
vLoad: Vstack( 3) = 50.0± 1.20 2.4%
vSub: Vstack( 2) = 50.0± 2.59 5.2%
vSquare: Vstack( 2) = 2500.0±259.42 10.4%
vAdd: Vstack( 1) = 12500.0±556.15 4.4%
vSqrt: Vstack( 1) = 111.8± 2.49 2.2%
Distance 111.8±2.49</pre>
Although the example source file uses the F90 MODULE protocol, this is merely for convenience. Otherwise, there would be the same collection of routines, all sharing a COMMON work area. It would be easy enough to prepare an interactive calculator using this scheme so that different calculations (and data) could be more easily experimented with. Inspection might suggest a return to the laboratory in order to measure some factor with greater precision because its error proves to be the largest contributor to the spread in the result.
Line 757 ⟶ 1,014:
===Fortran 90 ''et seq''.===
A latter-day expansion of Fortran makes it possible to define a compound entity such as a value and its associated error, for instance,<
REAL VALUE
REAL SD
Line 766 ⟶ 1,023:
END TYPE POINT
TYPE(POINT) P1,P2
</syntaxhighlight>
Whereupon, instead of a swarm of separate variables named according to some scheme, you can have a collection of variables with subcomponents named systematically. Further, via a great deal of syntax one can devise functions dealing with those compound types and moreover, prepare procedures that will perform operations such as addition and subtraction, etc. and merge these with the ordinary usages of addition, etc. of ordinary variables. One would then write the formula to be calculated, and it would all just happen.
But with the details of the calculation's progress out of sight. This is probably not a good idea.
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">'----------------------
' definition of a "measurement" type with value and uncartainty
' and operators that can operate on them
'---------------------
#macro p2(x)
(x)*(x)
#endmacro
type meas
vlu as double
unc as double
end type
operator + ( a as meas, b as meas ) as meas
dim ret as meas
ret.vlu = a.vlu + b.vlu
ret.unc = sqr( a.unc*a.unc + b.unc*b.unc )
return ret
end operator
operator + ( c as double, a as meas ) as meas
dim ret as meas
ret.vlu = a.vlu + c
ret.unc = a.unc
return ret
end operator
operator + ( a as meas, c as double ) as meas
return c+a
end operator
operator - ( a as meas, b as meas ) as meas
dim ret as meas
ret.vlu = a.vlu - b.vlu
ret.unc = sqr( a.unc*a.unc + b.unc*b.unc )
return ret
end operator
operator - ( c as double, a as meas ) as meas
dim ret as meas
ret.vlu = a.vlu - c
ret.unc = a.unc
return ret
end operator
operator - ( a as meas, c as double ) as meas
dim ret as meas
ret.vlu = c - a.vlu
ret.unc = a.unc
return ret
end operator
operator * ( a as meas, b as meas ) as meas
dim ret as meas
ret.vlu = a.vlu*b.vlu
ret.unc = sqr(p2(ret.vlu) * (p2(a.unc/a.vlu)+p2(b.unc/b.vlu)))
return ret
end operator
operator * ( c as double, a as meas ) as meas
dim ret as meas
ret.vlu = a.vlu*c
ret.unc = abs(c*a.unc)
return ret
end operator
operator * ( a as meas, c as double ) as meas
return c*a
end operator
operator ^ ( a as meas, c as double ) as meas
dim ret as meas
ret.vlu = a.vlu ^ c
ret.unc = abs(ret.vlu*c*a.unc/a.vlu)
return ret
end operator
operator / ( c as double, a as meas ) as meas
return c*a^(-1)
end operator
operator / ( a as meas, c as double ) as meas
return a*(1.0/c)
end operator
operator / ( a as meas, b as meas ) as meas
return b*a^(-1)
end operator
sub printm( a as meas )
print using "####.##### +- ####.####"; a.vlu; a.unc
end sub
'--------------------------------
' now the results
'--------------------------------
dim as meas x1, y1, x2, y2
x1.vlu = 100.
x1.unc = 1.1
y1.vlu = 50.
y1.unc = 1.2
x2.vlu = 200.
x2.unc = 2.2
y2.vlu = 100.
y2.unc = 2.3
printm( ((x1-x2)^2 + (y1-y2)^2)^0.5 )</syntaxhighlight>
{{out}}<pre>
111.80340 +- 2.4872
</pre>
=={{header|Go}}==
Variance from task requirements is that the following does not "extend the language." It simply defines a type with associated functions and methods as required to solve the remainder of the task.
<
import (
Line 871 ⟶ 1,244:
fmt.Println("d: ", d.n)
fmt.Println("error:", d.errorTerm())
}</
Output:
<pre>
Line 879 ⟶ 1,252:
=={{header|Haskell}}==
<
instance (Floating a) => Num (Error a) where
Line 899 ⟶ 1,272:
x2 = Error 200 2.2
y2 = Error 100 2.3
</syntaxhighlight>
{{out}}
<pre>Error {value = 111.80339887498948, uncertainty = 2.4871670631463423}</pre>
Line 907 ⟶ 1,280:
The following solution works in both languages.
<
procedure main(a)
Line 949 ⟶ 1,322:
return (numeric(a)^numeric(b)) |
num(f := a.val^numeric(b), abs(f*b*(a.err/a.val)))
end</
The output is:
Line 965 ⟶ 1,338:
First, we will need some utilities. <code>num</code> will extract the number part of a number. <code>unc</code> will extract the uncertainty part of a number, and will also be used to associate uncertainty with a number. <code>dist</code> will compute the distance between two numbers (which is needed for multiplicative uncertainty).
<
unc=: {:@}."1 : ,.
dist=: +/&.:*:</
Note that if a number has no uncertainty assigned to it, we assume the uncertainty is zero.
Line 973 ⟶ 1,346:
Jumping into the example values, for illustration purposes:
<
y1=: 50 unc 1.2
x2=: 200 unc 2.2
y2=: 100 unc 2.3</
Above, we see <code>unc</code> being used to associate a number with its uncertainty. Here's how to take them apart again:
<
100
unc x1
1.1</
Note that these operations "do the right thing" for normal numbers:
<
100
unc 100
0</
And, a quick illustration of the distance function:
<syntaxhighlight lang="text"> 3 dist 4
5</
Next, we need to define our arithmetic operations:
<
sub=: -&num unc dist&unc
mul=: *&num unc |@(*&num * dist&(unc%num))
div=: %&num unc |@(%&num * dist&(unc%num))
exp=: ^&num unc |@(^&num * dist&(unc%num))</
Finally, our required example:
<
111.803 2.48717</
=={{header|Java}}==
<
private double value;
private double error;
Line 1,097 ⟶ 1,470:
System.out.println(x1);
}
}</
{{out}}
<pre>111.80339887498948±2.4871670631463423</pre>
=={{header|Julia}}==
=== Using Measurements library ===
<syntaxhighlight lang="julia">
using Measurements
x1 = measurement(100, 1.1)
x2 = measurement(200, 2.2)
y1 = measurement(50, 1.2)
y2 = measurement(100, 2.3)
d = sqrt((x1 - x2)^2 + (y1 - y2)^2)
@show d
@show d.val, d.err
</syntaxhighlight>{{out}}
The Measurements library will round to correct decimal place precision when displaying tolerances, so the fields are shown to show the calculations are equivalent.
<pre>
d = 111.8 ± 2.5
(d.val, d.err) = (111.80339887498948, 2.4871670631463423)
</pre>
=== With custom module ===
<syntaxhighlight lang="julia">module NumericError
import Base: convert, promote_rule, +, -, *, /, ^
export Measure
type Measure <: Number
x::Float64
σ::Float64
Measure(x::Real) = new(Float64(x), 0)
Measure(x::Real, σ::Real) = new(Float64(x), σ)
end
Base.show(io::IO, x::Measure) = print(io, string(x.x, " ± ", x.σ))
Base.convert(::Type{Measure}, x::Real) = Measure(Float64(x), 0.0)
Base.promote_rule(::Type{Float64}, ::Type{Measure}) = Measure
Base.promote_rule(::Type{Int64}, ::Type{Measure}) = Measure
+(a::Measure, b::Measure) = Measure(a.x + b.x, sqrt(a.σ ^ 2 + b.σ ^ 2))
-(a::Measure, b::Measure) = Measure(a.x - b.x, sqrt(a.σ ^ 2 + b.σ ^ 2))
-(a::Measure) = Measure(-a.x, a.σ)
*(a::Measure, b::Measure) = begin
x = a.x * b.x
σ = sqrt(x ^ 2 * ((a.σ / a.x) ^ 2 + (b.σ / b.x) ^ 2))
Measure(x, σ)
end
/(a::Measure, b::Measure) = begin
x = a.x / b.x
σ = sqrt(x ^ 2 * ((a.σ / a.x) ^ 2 + (b.σ / b.x) ^ 2))
Measure(x, σ)
end
^(a::Measure, b::Float64) = begin
x = a.x ^ b
σ = abs(x * b * a.σ / a.x)
Measure(x, σ)
end
Base.sqrt(a::Measure) = a ^ .5
end # module NumericError
using NumericError
# x1 = 100 ± 1.1
# y1 = 50 ± 1.2
# x2 = 200 ± 2.2
# y2 = 100 ± 2.3
x1 = Measure(100, 1.1)
y1 = Measure(50, 1.2)
x2 = Measure(200, 2.2)
y2 = Measure(100, 2.3)
d = sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
@show x1 y1 x2 y2 sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
</syntaxhighlight>
{{out}}
<pre>
x1 = 100.0 ± 1.1
y1 = 50.0 ± 1.2
x2 = 200.0 ± 2.2
y2 = 100.0 ± 2.3
sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2) = 111.80339887498948 ± 1.7586926962946086
</pre>
=={{header|Kotlin}}==
{{trans|Java}}
<
data class Approx(val ν: Double, val σ: Double = 0.0) {
Line 1,141 ⟶ 1,606:
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))
}</
{{out}}
<pre>111.80339887498948 ±2.4871670631463423</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
PlusMinus /: a_ ± σa_ + b_ ± σb_ := N[(a + b) ± Norm@{σa, σb}];
PlusMinus /: c_?NumericQ (a_ ± σa_) := N[c a ± Abs[c σa]];
PlusMinus /: (a_ ± σa_) (b_ ± σb_) := N[a b ± (a b Norm@{σa/a, σb/b})^2];
PlusMinus /: (a_ ± σa_)^c_?NumericQ := N[a^c ± Abs[a^c σa/a]];</
<
y1 = 50 ± 1.2;
x2 = 200 ± 2.2;
y2 = 100 ± 2.3;
d = Sqrt[(x1 - x2)^2 + (y1 - y2)^2]</
{{Out}}
<pre>111.803 ± 2.48717</pre>
===Native implementation===
<syntaxhighlight lang="mathematica">x1 = Around[100, 1.1];
y1 = Around[50, 1.2];
x2 = Around[200, 2.2];
y2 = Around[100, 2.3];
d = Sqrt[(x1 - x2)^2 + (y1 - y2)^2]</syntaxhighlight>
{{out}}
<pre>111.8\[PlusMinus]2.5</pre>
=={{header|Nim}}==
<syntaxhighlight lang="nim">import strformat
import math
type
Imprecise = object
x: float
σ: float
template `^`(a, b: float): float =
pow(a, b)
template `-`(a: Imprecise): Imprecise =
Imprecise(x: -a.x, σ: a.σ)
template `+`(a, b: Imprecise): Imprecise =
Imprecise(x: a.x + b.x, σ: sqrt(a.σ ^ 2 + b.σ ^ 2))
template `-`(a, b: Imprecise): Imprecise =
Imprecise(x: a.x - b.x, σ: sqrt(a.σ ^ 2 + b.σ ^ 2))
template `*`(a, b: Imprecise): Imprecise =
let x = a.x * b.x
let σ = sqrt(x ^ 2 * ((a.σ / a.x) ^ 2 + (b.σ / b.x) ^ 2))
Imprecise(x: x, σ: σ)
template `/`(a, b: Imprecise): Imprecise =
let x = a.x / b.x
let σ = sqrt(x ^ 2 * ((a.σ / a.x) ^ 2 + (b.σ / b.x) ^ 2))
Imprecise(x: x, σ: σ)
template `^`(a: Imprecise, b: float): Imprecise =
if b < 0:
raise newException(IOError, "Cannot raise to negative power.")
let x = a.x ^ b
let σ = abs(x * b * a.σ / a.x)
Imprecise(x: x, σ: σ)
template sqrt(a: Imprecise): Imprecise =
a ^ 0.5
proc `$`(a: Imprecise): string =
fmt"{a.x:.2f} ± {a.σ:.2f}"
var x1 = Imprecise(x: 100, σ: 1.1)
var y1 = Imprecise(x: 50, σ: 1.2)
var x2 = Imprecise(x: 200, σ: 2.2)
var y2 = Imprecise(x: 100, σ: 2.3)
echo sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2)</syntaxhighlight>
{{out}}
<pre>
111.80 ± 2.49
</pre>
=={{header|PARI/GP}}==
''This is a work-in-progress.''
<
sub(a,b)=if(type(a)==type(b), [a[1]-b[1],a[2]+b[2]], if(type(a)=="t_VEC",a-[b,0],[a,0]-b));
mult(a,b)=if(type(a)=="t_VEC", if(type(b)=="t_VEC", [a[1]*b[1], abs(a[1]*b[1])*sqrt(norml2([a[2]/a[1],b[2]/b[1]]))], [b*a[1], abs(b)*a[2]]), [a*b[1], abs(a)*b[2]]);
Line 1,167 ⟶ 1,689:
pow(a,b)=[a[1]^b, abs(a[1]^b*b*a[2]/a[1])];
x1=[100,1.1];y1=[50,1.2];x2=[200,2.2];y2=[100,2.3];
pow(add(pow(sub(x1,x2),2),pow(sub(y1,y2),2)),.5)</
=={{header|Perl}}==
Following code keeps track of covariance between variables. Each variable with error contains its mean value and components of error source from a set of
<
package ErrVar;
# helper function, apply function 'f' to pairs (a, b) from listX and listY
sub zip (
$y = [(0) x @$x] unless @$y; # if not defined
\@out
}
use overload
'sqrt' => \&_sqrt,
;
# make a variable with mean value and a list of coefficient to
# variables providing independent errors
sub make ($x, @v) { bless [$x, @v] }
# mean value of the var, or just the input if it's not of this class
sub mean ($x) { ref $x && $x->isa(__PACKAGE__) ? $x->[0] : $x }
# return variance index array
sub vlist ($x) { ref $x && $x->isa(__PACKAGE__) ? $x->[1] : [] }
sub variance ($x) {
return 0 unless ref($x) and $x->isa(__PACKAGE__);
my $s;
$s += $_ * $_ for @{$x->[1]};
$s
}
sub covariance ($x, $y) {
return 0 unless ref($x) && $x->isa(__PACKAGE__);
my $s;
zip sub ($a,$b) { $s += $a * $b }, vlist($x), vlist($y);
}
sub sigma ($v) { sqrt variance
# to determine if a var is probably zero. we use 1σ here
sub _bool ($x, $, $) {
abs(mean $x) > sigma $x
}
sub _ncmp ($a, $b, $) {
}
sub _neg ($x, $, $) {
bless [ -mean($x), [map(-$_, @{vlist $x}) ] ];
}
sub _add ($x, $y, $) {
bless [$x0 + $y0, zip sub ($a,$b) {$a + $b}, $xv, $yv]
}
sub _sub ($x, $y, $) {
}
sub _mul ($x, $y, $) {
$yv = [ map($x0 * $_, @$yv) ];
}
sub _div ($x, $y, $) {
$xv = [ map($_/$y0, @$xv) ];
bless [$x0 / $y0, zip sub ($a,$b) {$a + $b}, $xv, $yv]
}
sub _sqrt ($x, $, $) {
my ($x0, $xv) = ( mean($x), vlist($x) );
bless [$x0, $xv]
}
sub _pow ($x, $y, $) {
die "Can't take pow of negative number $x" if int($y) != $y or $y & 1;
}
exp($y * log $x)
}
sub _exp ($x, $, $) {
my ($x0, $xv) = ( exp(mean($x)), vlist($x) );
bless [ $x0, [map($x0 * $_, @$xv) ] ]
}
sub _log ($x, $, $) {
my ($x0, $xv) = ( mean($x), vlist($x) );
bless [ log($x0), [ map($_ / $x0, @$xv) ] ]
}
sub _str { sprintf '%g±%.3g', $_[0][0], sigma($_[0]) }
package main;
Line 1,351 ⟶ 1,828:
my $z1 = sqrt(($x1 - $x2) ** 2 + ($y1 - $y2) ** 2);
# this is not for task requirement
my $a = $x1 + $x2;
my $b = $y1 - 2 * $x2;
{{out}}
<pre>distance: 111.803±2.49
covariance between 300±2.46 and -350±4.56: -9.68</pre>
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">VALUE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DELTA</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">imprecise</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">imp</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imp</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">*</span><span style="color: #000000;">a</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">imprecise_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imprecise</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">delta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">]))</span>
<span style="color: #000000;">imprecise</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">delta</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">imprecise_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imprecise</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">delta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">]))</span>
<span style="color: #000000;">imprecise</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">],</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">imprecise_div</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imprecise</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">delta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">]))/</span><span style="color: #000000;">sqr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">imprecise</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">delta</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">imprecise_pow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imprecise</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">delta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">*</span><span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DELTA</span><span style="color: #0000FF;">]/</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VALUE</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">imprecise</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">v</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ret</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">printImprecise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imprecise</span> <span style="color: #000000;">imp</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%g+/-%g"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">imp</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000000;">imprecise</span> <span style="color: #000000;">x1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.1</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">y1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.2</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">x2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">200</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2.2</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">y2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2.3</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">tmp1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp2</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">d</span>
<span style="color: #000000;">tmp1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imprecise_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">tmp1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imprecise_pow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">tmp2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imprecise_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">tmp2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imprecise_pow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imprecise_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imprecise_pow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Distance, d, between the following points :"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n( x1, y1) = ( %s, %s)"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">printImprecise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">printImprecise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n( x2, y2) = ( %s, %s)"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">printImprecise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">printImprecise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nis d = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">printImprecise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
Aside: obviously you don't ''have'' to use tmp1/2 like that, but I find that style often makes things much easier to debug.
{{out}}
<pre>
Distance, d, between the following points :
( x1, y1) = ( 100+/-1.1, 50+/-1.2)
( x2, y2) = ( -200+/-2.2, -100+/-2.3)
is d = 111.803+/-2.48717
</pre>
=={{header|PicoLisp}}==
Line 1,471 ⟶ 1,911:
The overloaded +, -, * and / operators look a bit complicated, because they must handle an arbitrary number of arguments to be compatible with the standard operators.
<
(load "@lib/math.l")
Line 1,564 ⟶ 2,004:
(round (car N) 10)
" ± "
(round (sqrt (cdr N) 1.0) 8) ) ) )</
Test:
<
(**
(+ (** (- X1 X2) 2.0) (** (- Y1 Y2) 2.0))
Line 1,577 ⟶ 2,017:
(unc 50. 1.2)
(unc 200. 2.2)
(unc 100. 2.3) ) ) )</
Output:
<pre>Distance: 111.8033988750 ± 2.48716706</pre>
=={{header|Python}}==
<
import math
Line 1,674 ⟶ 2,114:
p1, p2 = (x1, y1), (x2, y2)
print("Distance between points\n p1: %s\n and p2: %s\n = %r" % (
p1, p2, distance(p1, p2)))</
;Sample output:
Line 1,684 ⟶ 2,124:
=={{header|Racket}}==
{{trans|Mathematica}}
<
(struct ± (x dx) #:transparent
Line 1,725 ⟶ 2,165:
(define x2 (± 200 2.2))
(define y2 (± 100 2.3))
(norm (±- x1 x2) (±- y1 y2))</
{{output}}
<pre>111.803 ± 2.487</pre>
=={{header|Raku}}==
(formerly Perl 6)
{{Works with|rakudo|2018.03}}
{{trans|Perl}}
<syntaxhighlight lang="raku" line># cache of independent sources so we can make them all the same length.
# (Because Raku does not yet have a longest-zip metaoperator.)
my @INDEP;
class Approx does Numeric {
has Real $.x; # The mean.
has $.c; # The components of error.
multi method Str { sprintf "%g±%.3g", $!x, $.σ }
multi method Bool { abs($!x) > $.σ }
method variance { [+] @.c X** 2 }
method σ { sqrt self.variance }
}
multi approx($x,$c) { Approx.new: :$x, :$c }
multi approx($x) { Approx.new: :$x, :c[0 xx +@INDEP] }
# Each ± gets its own source slot.
multi infix:<±>($a, $b) {
.push: 0 for @INDEP; # lengthen older component lists
my $c = [ flat 0 xx @INDEP, $b ];
@INDEP.push: $c; # add new component list
approx $a, $c;
}
multi prefix:<->(Approx $a) { approx -$a.x, [$a.c.map: -*] }
multi infix:<+>($a, Approx $b) { approx($a) + $b }
multi infix:<+>(Approx $a, $b) { $a + approx($b) }
multi infix:<+>(Approx $a, Approx $b) { approx $a.x + $b.x, [$a.c Z+ $b.c] }
multi infix:<->($a, Approx $b) { approx($a) - $b }
multi infix:<->(Approx $a, $b) { $a - approx($b) }
multi infix:<->(Approx $a, Approx $b) { approx $a.x - $b.x, [$a.c Z- $b.c] }
multi covariance(Real $a, Real $b) { 0 }
multi covariance(Approx $a, Approx $b) { [+] $a.c Z* $b.c }
multi infix:«<=>»(Approx $a, Approx $b) { $a.x <=> $b.x }
multi infix:<cmp>(Approx $a, Approx $b) { $a.x <=> $b.x }
multi infix:<*>($a, Approx $b) { approx($a) * $b }
multi infix:<*>(Approx $a, $b) { $a * approx($b) }
multi infix:<*>(Approx $a, Approx $b) {
approx $a.x * $b.x,
[$a.c.map({$b.x * $_}) Z+ $b.c.map({$a.x * $_})];
}
multi infix:</>($a, Approx $b) { approx($a) / $b }
multi infix:</>(Approx $a, $b) { $a / approx($b) }
multi infix:</>(Approx $a, Approx $b) {
approx $a.x / $b.x,
[ $a.c.map({ $_ / $b.x }) Z+ $b.c.map({ $a.x * $_ / $b.x / $b.x }) ];
}
multi sqrt(Approx $a) {
my $x = sqrt($a.x);
approx $x, [ $a.c.map: { $_ / 2 / $x } ];
}
multi infix:<**>(Approx $a, Real $b) { $a ** approx($b) }
multi infix:<**>(Approx $a is copy, Approx $b) {
my $ax = $a.x;
my $bx = $b.x;
my $fbx = floor $b.x;
if $ax < 0 {
if $fbx != $bx or $fbx +& 1 {
die "Can't take power of negative number $ax";
}
$a = -$a;
}
exp($b * log $a);
}
multi exp(Approx $a) {
my $x = exp($a.x);
approx $x, [ $a.c.map: { $x * $_ } ];
}
multi log(Approx $a) {
my $x0 = $a.x;
approx log($x0), [ $a.c.map: { $_ / $x0 }];
}
# Each ± sets up an independent source component.
my $x1 = 100 ± 1.1;
my $x2 = 200 ± 2.2;
my $y1 = 50 ± 1.2;
my $y2 = 100 ± 2.3;
# The standard task.
my $z1 = sqrt(($x1 - $x2) ** 2 + ($y1 - $y2) ** 2);
say "distance: $z1\n";
# Just showing off.
my $a = $x1 + $x2;
my $b = $y1 - 2 * $x2;
say "covariance between $a and $b: ", covariance($a,$b);</syntaxhighlight>
{{out}}
<pre>distance: 111.803±2.49
covariance between 300±2.46 and -350±4.56: -9.68</pre>
=={{header|REXX}}==
{{trans|Fortran}}
<
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
parse var ax ax '±' axe; parse var bx bx '±' bxE
parse var ay ay '±' aye; parse var by by '±' byE
if axE=='' then axE= 0; if bxE==
if ayE=='' then ayE= 0; if byE==
say ' A point (x,y)= ' ax "±" axE', ' ay "±" ayE
say ' B point (x.y)= ' bx "±" bxE', ' by "±" byE
say /*blank line for the eyeballs.*/
dx= ax-bx; dxE= sqrt(axE**2 + bxE**2);
dy= ay-by; dyE= sqrt(ayE**2 + byE**2);
D= sqrt(dx**2 + dy**2)
say 'distance=' D "±" #(D**2, .5, sqrt(xE**2 + yE**2)) /*display " " " */
exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
#: procedure; arg x,p,e
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits();
numeric
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
/*──────────────────────────────────────────────────────────────────────────────────────*/
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</syntaxhighlight>
{{out|output|text= when using the default inputs:}}
<pre>
A point (x,y)= 100 ± 1.1, 50 ± 1.2
Line 1,766 ⟶ 2,321:
=={{header|Ruby}}==
<
def initialize(number, error)
@num = number
Line 1,829 ⟶ 2,384:
y2 = NumberWithUncertainty.new(100, 2.3)
puts ((x1 - x2) ** 2 + (y1 - y2) ** 2).sqrt</
{{out
<pre>111.803398874989 ± 2.48716706314634</pre>
=={{header|Scala}}==
{{trans|Kotlin}}
<
class Approx(val ν: Double, val σ: Double = 0.0) {
Line 1,877 ⟶ 2,432:
val y2 = Approx(100.0, 2.3)
println(√(((x1 - x2)^2.0) + ((y1 - y2)^2.0))) // => 111.80339887498948 ±2.938366893361004
}</
{{out}}
<pre>111.80339887498948 ±2.938366893361004</pre>
=={{header|Swift}}==
<syntaxhighlight lang="swift">import Foundation
precedencegroup ExponentiationGroup {
higherThan: MultiplicationPrecedence
}
infix operator ** : ExponentiationGroup
infix operator ±
func ±(_ lhs: Double, _ rhs: Double) -> UncertainDouble { UncertainDouble(value: lhs, error: rhs) }
struct UncertainDouble {
var value: Double
var error: Double
static func +(_ lhs: UncertainDouble, _ rhs: UncertainDouble) -> UncertainDouble {
return UncertainDouble(value: lhs.value + rhs.value, error: pow(pow(lhs.error, 2) + pow(rhs.error, 2), 0.5))
}
static func +(_ lhs: UncertainDouble, _ rhs: Double) -> UncertainDouble {
return UncertainDouble(value: lhs.value + rhs, error: lhs.error)
}
static func -(_ lhs: UncertainDouble, _ rhs: UncertainDouble) -> UncertainDouble {
return UncertainDouble(value: lhs.value - rhs.value, error: pow(pow(lhs.error, 2) + pow(rhs.error, 2), 0.5))
}
static func -(_ lhs: UncertainDouble, _ rhs: Double) -> UncertainDouble {
return UncertainDouble(value: lhs.value - rhs, error: lhs.error)
}
static func *(_ lhs: UncertainDouble, _ rhs: UncertainDouble) -> UncertainDouble {
let val = lhs.value * rhs.value
return UncertainDouble(
value: val,
error: pow(pow(val, 2) * (pow(lhs.error / lhs.value, 2) + pow(rhs.error / rhs.value, 2)), 0.5)
)
}
static func *(_ lhs: UncertainDouble, _ rhs: Double) -> UncertainDouble {
return UncertainDouble(value: lhs.value * rhs, error: abs(lhs.error * rhs))
}
static func /(_ lhs: UncertainDouble, _ rhs: UncertainDouble) -> UncertainDouble {
let val = lhs.value / rhs.value
return UncertainDouble(
value: val,
error: pow(val, 2) * (pow(lhs.error / lhs.value, 2) + pow(rhs.error / rhs.value, 2))
)
}
static func /(_ lhs: UncertainDouble, _ rhs: Double) -> UncertainDouble {
return UncertainDouble(value: lhs.value / rhs, error: abs(lhs.error * rhs))
}
static func **(_ lhs: UncertainDouble, _ power: Double) -> UncertainDouble {
let val = pow(lhs.value, power)
return UncertainDouble(value: val, error: abs((val * power) * (lhs.error / lhs.value)))
}
}
extension UncertainDouble: CustomStringConvertible {
public var description: String { "\(value) ± \(error)" }
}
let (x1, y1) = (100 ± 1.1, 50 ± 1.2)
let (x2, y2) = (200 ± 2.2, 100 ± 2.3)
let d = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
print(d)</syntaxhighlight>
{{out}}
<pre>111.80339887498948 ± 2.4871670631463423</pre>
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
Firstly, some support code for doing RAII-like things, evolved from code in the [[Quaternion type#Tcl|quaternion]] solution:
<
oo::class create RAII-support {
constructor {} {
Line 1,937 ⟶ 2,573:
try $script on ok msg {$msg return}
] [uplevel 1 {namespace current}]] {*}$vals
}</
The implementation of the number+error class itself:
<
variable N E
constructor {number {error 0.0}} {
Line 1,989 ⟶ 2,625:
export + - * / **
}</
Demonstrating:
<
set x2 [Err 200 2.2]
set y1 [Err 50 1.2]
Line 1,999 ⟶ 2,635:
[[[$x1 - $x2] ** 2] + [[$y1 - $y2] ** 2]] ** 0.5
}]
puts "d = [$d p]"</
Output:
<pre>
d = 111.80339887498948 ± 2.4871670631463423
</pre>
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">class Approx {
construct new(nu, sigma) {
_nu = nu
_sigma = sigma
}
static new(a) {
if (a is Approx) return Approx.new(a.nu, a.sigma)
if (a is Num) return Approx.new(a, 0)
}
nu { _nu }
sigma { _sigma }
+(a) {
if (a is Approx) return Approx.new(_nu + a.nu, (_sigma *_sigma + a.sigma*a.sigma).sqrt)
if (a is Num) return Approx.new(_nu + a, _sigma)
}
-(a) {
if (a is Approx) return Approx.new(_nu - a.nu, (_sigma *_sigma + a.sigma*a.sigma).sqrt)
if (a is Num) return Approx.new(_nu - a, _sigma)
}
*(a) {
if (a is Approx) {
var v = _nu * a.nu
return Approx.new(v, (v*v*_sigma*_sigma/(_nu*_nu) + a.sigma*a.sigma/(a.nu*a.nu)).sqrt)
}
if (a is Num) return Approx.new(_nu*a, (a*_sigma).abs)
}
/(a) {
if (a is Approx) {
var v = _nu / a.nu
return Approx.new(v, (v*v*_sigma*_sigma/(_nu*_nu) + a.sigma*a.sigma/(a.nu*a.nu)).sqrt)
}
if (a is Num) return Approx.new(_nu/a, (a*_sigma).abs)
}
pow(d) {
var v = _nu.pow(d)
return Approx.new(v, (v*d*_sigma/_nu).abs)
}
toString { "%(_nu) ±%(_sigma)" }
}
var x1 = Approx.new(100, 1.1)
var y1 = Approx.new( 50, 1.2)
var x2 = Approx.new(200, 2.2)
var y2 = Approx.new(100, 2.3)
System.print(((x1 - x2).pow(2) + (y1 - y2).pow(2)).pow(0.5))</syntaxhighlight>
{{out}}
<pre>
111.80339887499 ±2.4871670631463
</pre>
|