1Number::WithError(3) User Contributed Perl Documentation Number::WithError(3)
2
3
4
6 Number::WithError - Numbers with error propagation and scientific
7 rounding
8
10 use Number::WithError;
11
12 my $num = Number::WithError->new(5.647, 0.31);
13 print $num . "\n";
14 # prints '5.65e+00 +/- 3.1e-01'
15 # (I.e. it automatically does scientific rounding)
16
17 my $another = $num * 3;
18 print $another . "\n";
19 # propagates the error assuming gaussian errors
20 # prints '1.69e+01 +/- 9.3e-01'
21
22 # trigonometric functions also work:
23 print sin($another) . "\n";
24 # prints '-9.4e-01 +/- 3.1e-01'
25
26 my $third = $another ** $num;
27 print $third. "\n";
28 # propagates both errors into one.
29 # prints '8.7e+06 +/- 8.1e+06'
30
31 # shortcut for the constructor:
32 use Number::WithError 'witherror';
33 $num = witherror('0.00032678', ['2.5e-5', '3e-5'], 5e-6);
34 # can deal with any number of errors, even with asymmetric errors
35 print $num . "\n";
36 # prints '3.268e-04 + 2.5e-05 - 3.00e-05 +/- 5.0e-06'
37 # Note: It may be annyoing that they don't all have the same
38 # exponent, but they *do* all have the sam significant digit!
39
41 This class is a container class for numbers with a number of associated
42 symmetric and asymmetric errors. It overloads practically all common
43 arithmetic operations and trigonometric functions to propagate the
44 errors. It can do proper scientific rounding (as explained in more
45 detail below in the documentation of the "significant_digit()" method).
46
47 You can use Math::BigFloat objects as the internal representation of
48 numbers in order to support arbitrary precision calculations.
49
50 Errors are propagated using Gaussian error propagation.
51
52 With a notable exception, the test suite covers way over ninety percent
53 of the code. The remaining holes are mostly difficult-to-test corner
54 cases and sanity tests. The comparison routines are the exception for
55 which there will be more extensive tests in a future release.
56
58 This module uses overload to enable the use of the ordinary Perl
59 arithmetic operators on objects. All overloaded operations are also
60 availlable via methods. Here is a list of overloaded operators and the
61 equivalent methods. The assignment forms of arithmetic operators (e.g.
62 "+=") are availlable if their normal counterpart is overloaded.
63
64 • Addition: "$x + $y" implemented by the "$x->add($y)" method.
65
66 • Increment: "$x++" implemented by the "$x->add(1)" method.
67
68 • Subtraction: "$x - $y" implemented by the "$x->subtract($y)" method
69
70 • Decrement: "$x--" implemented by the "$x->subtract(1)" method.
71
72 • Multiplication: "$x * $y" implemented by the "$x->multiply($y)"
73 method.
74
75 • Division: "$x / $y" implemented by the "$x->divide($y)" method.
76
77 • Exponentiation: "$x ** $y" implemented by the "$x->exponentiate($y)"
78 method.
79
80 • Sine: "sin($x)" implemented by the "$x->sin()" method.
81
82 • Cosine: "cos($x)" implemented by the "$x->cos()" method.
83
84 • Stringification "$x" is implemented by the "$x->round()" method.
85
86 • Cast to a number (i.e. numeric context) is implemented by the
87 "$x->number()" method.
88
89 • Boolean context is implemented by the "$x->number()" method.
90
91 • Unary minus "-$x" is implemented by the "$x->multiply(-1)" method.
92
93 • Logical not is implemented via a boolean context.
94
95 • Absolute value "abs($x)" is implemented via "$x->abs()".
96
97 • Natural logarithm "log($x)" is implemented via "$x->log()".
98
99 • Square Root "sqrt($x)" is implemented via "$x->sqrt()".
100
101 • Numeric comparison operators "$x == $y", "$x != $y", etc. are
102 implemented via "$x-$<gt"numeric_cmp($y)>.
103
104 • String comparison operators "$x eq $y", "$x ne $y", etc. are
105 implemented via "$x-$<gt"full_cmp($y)>. They might not do what you
106 expect. Please read the documentation.
107
108 Here's a list of overloadable operations that aren't overloaded in the
109 context of this module:
110
111 << >> x . & ^ | atan2 int
112
114 All constructors accept Math::BigFloat objects in place of numbers.
115
116 new
117 This is the basic constructor for "Number::WithError" objects.
118
119 New objects can be created in one of two ways:
120
121 • The first argument is expected to be the number itself. Then come
122 zero or more errors. Errors can either be a number, a reference to an
123 array of two numbers, or "undef". In the former case, the number is
124 treated as an uncertainty which has the same magnitude in both
125 directions. (I.e. "+/- x") In case of an array reference, the first
126 number is treated as the upper error boundary and the second as the
127 lower boundary. (I.e. "+x, -y") "undef" is treated as zero error.
128
129 • The second way to create objects is passing a single string to the
130 constructor which is efficiently parsed into a number and any number
131 of errors. I'll explain the format with an example:
132
133 133.14e-5 +/- .1e-4 + 0.00002 - 1.0e-5 +/- .2e-4
134
135 In this example, the first number is parsed as the actual number.
136 The following number is treated as a symmetric error (".1e-4") The
137 two following numbers are treated as the upper and lower boundary for
138 a single error. Then comes another ordinary error. It is also legal
139 to define the lower boundary of an error before the upper boundary.
140 (I.e. "-1.0e-5 +0.00002")
141
142 Whitespace is insignificant.
143
144 For the sake of completeness, I'll mention the regular expression
145 that is used to match numbers. It's taken from the official Perl FAQ
146 to match floating point numbers:
147
148 [+-]?(?=\d|\.\d)\d*(?:\.\d*)?(?:[Ee][+-]?\d+)?
149
150 Don't worry if you don't understand it. Just run a few tests to see
151 if it'll accept your numbers. Or go read "perldoc -q float" or pick
152 up a book on C and read up on how they define floating point numbers.
153
154 Note that trailing zeros currently have no effect. (Yes, this is a
155 BUG!)
156
157 The constructor returns a new object of this class or undef if
158 something went wrong.
159
160 new_big
161 This is an alternative constructor for "Number::WithError" objects. It
162 works exactly like "new" except that it makes all internal numbers
163 instances of "Math::BigFloat" for high precision calculations.
164
165 The module does not load "Math::BigFloat" at compile time to avoid
166 loading a big module that isn't needed all the time. Instead, this
167 module makes use of the prefork pragma and loads "Math::BigFloat" when
168 needed at run-time.
169
170 witherror
171 This constructor is not a method. It is a subroutine that can be
172 exported to your namespace on demand. It works exactly as the "new()"
173 method except it's a subroutine and shorter.
174
175 I'm normally not for this kind of shortcut in object-oriented code, but
176 if you have to create a large number of "Number::WithError" numbers,
177 you'll appreciate it. Trust me.
178
179 Note to authors of subclasses: If you inherit from this module, you'll
180 need to implement your own "witherror()" because otherwise, it will
181 still return objects of this class, not your subclass.
182
183 witherror_big
184 This is also not a method. It does the same as "witherror()". It can
185 also be optionally be exported to your namespace.
186
187 It uses the "new_big" constructor instead of the "new" constructor used
188 by "witherror()".
189
191 All of these methods implement an arithmetic operation on the object
192 and the method's first parameter.
193
194 The methods aren't mutators. That means they don't modify the object
195 itself, but return the result of the operation as a new object.
196
197 All of the methods accept either a plain number, a "Number::WithError"
198 object or anything that is understood by the constructors as argument,
199
200 All errors are correctly propagated using Gaussian Error Propagation.
201 The formulae used for this are mentioned in the individual methods'
202 documentation.
203
204 add
205 Adds the object a and the argument b. Returns a new object c.
206
207 Formula: "c = a + b"
208
209 Error Propagation: "err_c = sqrt( err_a^2 + err_b^2 )"
210
211 subtract
212 Subtracts the argument b from the object a. Returns a new object c.
213
214 Formula: "c = a - b"
215
216 Error Propagation: "err_c = sqrt( err_a^2 + err_b^2 )"
217
218 multiply
219 Multiplies the object a and the argument b. Returns a new object c.
220
221 Formula: "c = a * b"
222
223 Error Propagation: "err_c = sqrt( b^2 * err_a^2 + a^2 * err_b^2 )"
224
225 divide
226 Divides the object a by the argument b. Returns a new object c.
227
228 Formula: "c = a / b"
229
230 Error Propagation: "err-c = sqrt( err_a^2 / b^2 + a^2 * err_b^2 / b^4
231 )"
232
233 exponentiate
234 Raises the object a to the power of the argument b. Returns a new
235 object c. Returns "undef" if a is negative because the error cannot be
236 propagated in that case. (Can't take log of a negative value.)
237
238 Also, please have a look at the error propagation formula below.
239 Exponentiation and logarithms are operations that can become
240 numerically unstable very easily.
241
242 Formula: "c = a ^ b"
243
244 Error Propagation: "err-c = sqrt( b^2 * a^(b-1) * err_a^2 + ln(a)^2 *
245 a^b * err_b^2 )"
246
248 These methods calculate functions of the object and return the result
249 as a new object.
250
251 sqrt
252 Calculates the square root of the object a and returns the result as a
253 new object c. Returns undef if a is negative.
254
255 Formula: "c = sqrt(a)"
256
257 Error Propagation: "err-c = sqrt( err-a^2 / (2*sqrt(a))^2 ) = abs(
258 err-a / (2*sqrt(a)) )"
259
260 log
261 Calculates the natural logarithm of an object a. Returns a new object
262 c. If a is negative, the function returns undef.
263
264 Formula: "c = log(a)"
265
266 Error Propagation: "err-c = sqrt( err-a^2 / a^2 ) = abs( err-a / a )"
267
268 sin
269 Calculates the sine of the object a and returns the result as a new
270 object c.
271
272 Formula: "c = sin(a)"
273
274 Error Propagation: "err-c = sqrt( cos(a)^2 * err-a^2 ) = abs( cos(a) *
275 err-a )"
276
277 cos
278 Calculates the cosine of the object a and returns the result as a new
279 object c.
280
281 Formula: "c = cos(a)"
282
283 Error Propagation: "err-c = sqrt( sin(a)^2 * err-a^2 ) = abs( sin(a) *
284 err-a )"
285
286 tan
287 Calculates the tangent of the object a and returns the result as a new
288 object c.
289
290 Formula: "c = tan(a)"
291
292 Error Propagation: "err-c = sqrt( err-a^2 / cos(a)^4 ) = abs( err-a /
293 cos(a)^2 )"
294
295 Since there is no built-in "tan()" function, this operation is not
296 available via the overloaded interface.
297
298 abs
299 Calculates the absolute value of an object a. Leaves the errors
300 untouched. Returns a new object c.
301
302 Formula: "c = abs(a)"
303
304 Error Propagation: "err-c = err-a"
305
307 This section documents methods dealing with the extraction of data from
308 the object. The methods implement rounding of numbers, stringification
309 of the object and extracting meta information like the significant
310 digit.
311
312 number
313 Determines the significant digit using the "significant_digit()"
314 method, rounds the number that the object "number()" is called on
315 represents to that digit and returns the rounded number.
316
317 Regardless of the internal representation of the number, this returns
318 an unblessed string / an unblessed floating point number.
319
320 To gain access to the raw number representation in the object, use the
321 "raw_number" method.
322
323 Either way, the number will be in scientific notation. That means the
324 first non-zero digit comes before the decimal point and following the
325 decimal point and any number of digits is an exponent in "eXXX"
326 notation.
327
328 raw_number
329 This method returns the internal representation of the number in the
330 object. It does not round as appropriate. It does not clone
331 "Math::BigFloat" objects either. So make sure you do that if necessary!
332
333 round
334 This method determines the significant digit using the
335 "significant_digit()" method. Then, it rounds the number represented by
336 the object and all associated errors to that digit.
337
338 Then, the method concatenates the number with its errors and returns
339 the resulting string. In case of symmetric errors, the string "+/-"
340 will be prepended to the error. In case of asymmetric errors, a "+"
341 will be prepended to the first/upper error component and a "-" to the
342 second/lower error component.
343
344 Returns the previously described string.
345
346 significant_digit
347 This method returns the significant digit of the number it is called on
348 as an integer. If the number has no errors or all errors are "undef" or
349 zero, this method returns "undef".
350
351 The return value of this method is to be interpreted as follows: If
352 this method returns "-5", the significant digit is "1 * 10**-5" or
353 0.00001. If it returns 3, the significant digit is "1 * 10**3" or 1000.
354 If it returns 0, the significant digit is 1.
355
356 The return value is computed by the following algorithm: The individual
357 significant digit of a single error is: Take the exponent of the first
358 non-zero digit in the error. The digit after this first non-zero digit
359 is the significant one.
360
361 This method returns the minimum of the individual significant digits of
362 all errors.
363
364 That means:
365
366 5 +/- 0.0132 + 0.5 - 1
367
368 Will yield a return value of "-3" since the first error has the lowest
369 significant digit.
370
371 This algorithm is also used for determining the significant digit for
372 rounding. It is extremely important that you realize this isn't carved
373 in stone. The way the significant digit is computed in the presence of
374 errors is merely a convention. In this case, it stems from particle
375 physics. It might well be that in your particular scientific community,
376 there are other conventions. One, for example, is to use the second
377 non-zero digit only if the first is a 1.
378
379 error
380 This method returns a reference to an array of errors of the object it
381 is called on.
382
383 Unlike the "raw_error()" method, this method takes proper care to copy
384 all objects and references to defy action at a distance. The structure
385 of the returned array reference is akin to that returned by
386 "raw_error()".
387
388 Furthermore, this method rounds all errors to the significant digit as
389 determined by "significant_digit()".
390
391 raw_error
392 Returns the internal representation of the errors of the current
393 object. Note that (just like "raw_number()", this does not clone the
394 data for safe use without action at a distance. Instead, it directly
395 returns the internal reference to the error structure. The structure
396 is an array of errors. Each error may either be a string or floating
397 point number or a "Math::BigFloat" object or an array reference. In
398 case of an array reference, it is an asymmetric error. The inner array
399 contains two strings/numbers/"Math::BigFloat"s.
400
401 Note that this practically breaks encapsulation and code relying on it
402 might break with future releases.
403
404 as_array
405 This method returns the information stored in the object as an array
406 (i.e. a list in this context) which can be passed to the "new()" method
407 to recreate the object.
408
409 The first element of the return list will be the number itself. If the
410 object uses "Math::BigFloat" for the internal representation, this
411 element will be a copy of the internal object. Otherwise, it will be
412 the internal representation of the number with full precision.
413
414 Following the number will be all errors either as numbers,
415 "Math::BigFloat" objects or arrays containing two asymmetric errors.
416 (Either as numbers or objects as explained above.) The data returned by
417 this method will be copied deeply before being returned.
418
419 round_a_number
420 This is a helper function which can round a number to the specified
421 significant digit (defined as the return value of the
422 "significant_digit" method):
423
424 my $rounded = round_a_number(12.01234567, -3);
425 # $rounded is now 1.2012e01
426
428 This section lists methods that implement different comparisons between
429 objects.
430
431 numeric_cmp
432 This method implements a numeric comparison of two numbers. It
433 compares the object it is called on to the first argument of the
434 method. If the first argument is omitted or undefined, the method
435 returns "undef".
436
437 Numeric comparison means in this case that the represented numbers will
438 be rounded and then compared. If you would like a comparison that takes
439 care of errors, please have a look at the "full_cmp()" method.
440
441 The method returns "-1" if the rounded number represented by the object
442 is numerically less than the rounded number represented by the first
443 argument. It returns 0 if they are equal and 1 if the object's rounded
444 number is more than that of the argument.
445
446 This method implements the overloaded numeric comparison operations.
447
448 full_cmp
449 This method implements a full comparison of two objects. That means, it
450 takes their numeric values, rounds them and compares them just like the
451 "numeric_cmp()" method.
452
453 If, however, the numbers are equal, this method iterates over the
454 errors, rounds them and then compares them. If all errors are equal,
455 this method returns 0. If an error is found to differ, the method
456 returns 1 in case the object's error is larger and "-1" in case the
457 argument's error is larger.
458
459 Comparing an asymmetric error to a symmetric error is a special case.
460 It can never be the same error, hence the method will not return 0.
461 Instead, it guesses which error is larger by using the upper error
462 bound of the asymmetric error. (Well, yes, not very useful.)
463
465 Bugs should be reported via the CPAN bug tracker at
466
467 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Number-WithError>
468
469 For other issues, contact the author.
470
472 You may use Math::BigFloat with this module. Also, it should be
473 possible to use Math::Symbolic to calculate larger formulas. Just
474 assign a "Number::WithError" object to the "Math::Symbolic" variables
475 and it should work.
476
477 You also possibly want to have a look at the prefork pragma.
478
479 The test suite is implemented using the Test::LectroTest module. In
480 order to keep the total test time in reasonable bounds, the default
481 number of test attempts to falsify the test properties is kept at a low
482 number of 100. You can enable more rigorous testing by setting the
483 environment variable "PERL_TEST_ATTEMPTS" to a higher value. A value in
484 the range of 1500 to 3000 is probably a good idea, but takes a long
485 time to test.
486
488 Steffen Mueller <smueller@cpan.org>, <http://steffen-mueller.net/>
489
491 Copyright 2006-2010 Steffen Mueller.
492
493 This program is free software; you can redistribute it and/or modify it
494 under the same terms as Perl itself.
495
496
497
498perl v5.34.0 2022-01-21 Number::WithError(3)