]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/doc/fp_utilities/float_comparison.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / math / doc / fp_utilities / float_comparison.qbk
CommitLineData
7c673cae
FG
1[section:float_comparison Floating-point Comparison]
2
3[import ../../example/float_comparison_example.cpp]
4
5Comparison of floating-point values has always been a source of endless difficulty and confusion.
6
7Unlike integral values that are exact, all floating-point operations
8will potentially produce an inexact result that will be rounded to the nearest
9available binary representation. Even apparently inocuous operations such as assigning
100.1 to a double produces an inexact result (as this decimal number has no
11exact binary representation).
12
13Floating-point computations also involve rounding so that some 'computational noise' is added,
14and hence results are also not exact (although repeatable, at least under identical platforms and compile options).
15
16Sadly, this conflicts with the expectation of most users, as many articles and innumerable cries for help show all too well.
17
18Some background reading is:
19
20* Knuth D.E. The art of computer programming, vol II, section 4.2, especially Floating-Point Comparison 4.2.2, pages 198-220.
21* [@http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html David Goldberg, "What Every Computer Scientist Should Know About Floating-Point Arithmetic"]
22* [@http://adtmag.com/articles/2000/03/16/comparing-floatshow-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been-r.aspx
23Alberto Squassabia, Comparing floats listing]
24* [@https://code.google.com/p/googletest/wiki/AdvancedGuide#Floating-Point_Comparison Google Floating-Point_Comparison guide]
25* [@boost:/libs/test/doc/html/boost_test/users_guide/testing_tools/testing_floating_points.html Boost.Test Floating-Point_Comparison]
26
27Boost provides a number of ways to compare floating-point values to see if they are tolerably close enough to each other,
28but first we must decide what kind of comparison we require:
29
30* Absolute difference/error: the absolute difference between two values ['a] and ['b] is simply `fabs(a-b)`.
31This is the only meaningful comparison to make if we know that the result may have cancellation error (see below).
32* The edit distance between the two values: i.e. how many (binary) floating-point values are between two values ['a] and ['b]?
33This is provided by the function __float_distance, but is probably only useful when you know that the distance should be very small.
34This function is somewhat difficult to compute, and doesn't scale to values that are very far apart. In other words, use with care.
35* The relative distance/error between two values. This is quick and easy to compute, and is generally the method of choice when
36checking that your results are "tolerably close" to one another. However, it is not as exact as the edit distance when dealing
37with small differences, and due to the way floating-point values are encoded can "wobble" by a factor of 2 compared to the "true"
38edit distance. This is the method documented below: if `float_distance` is a surgeon's scalpel, then `relative_difference` is more
39like a Swiss army knife: both have important but different use cases.
40
41
42[h5:fp_relative Relative Comparison of Floating-point Values]
43
44
45`#include <boost/math/special_functions/relative_difference.hpp>`
46
47 template <class T, class U>
48 ``__sf_result`` relative_difference(T a, U b);
49
50 template <class T, class U>
51 ``__sf_result`` epsilon_difference(T a, U b);
52
53The function `relative_difference` returns the relative distance/error ['E] between two values as defined by:
54
55[pre E = fabs((a - b) / min(a,b))]
56
57The function `epsilon_difference` is a convenience function that returns `relative_difference(a, b) / eps` where
58`eps` is the machine epsilon for the result type.
59
60The following special cases are handled as follows:
61
62* If either of ['a] or ['b] is a NaN, then returns the largest representable value for T: for example for type `double`, this
63is `std::numeric_limits<double>::max()` which is the same as `DBL_MAX` or `1.7976931348623157e+308`.
64* If ['a] and ['b] differ in sign then returns the largest representable value for T.
65* If both ['a] and ['b] are both infinities (of the same sign), then returns zero.
66* If just one of ['a] and ['b] is an infinity, then returns the largest representable value for T.
67* If both ['a] and ['b] are zero then returns zero.
68* If just one of ['a] or ['b] is a zero or a denormalized value, then it is treated as if it were the
69smallest (non-denormalized) value representable in T for the purposes of the above calculation.
70
71These rules were primarily designed to assist with our own test suite, they are designed to be robust enough
72that the function can in most cases be used blindly, including in cases where the expected result is actually
73too small to represent in type T and underflows to zero.
74
75[h5 Examples]
76
77[compare_floats_using]
78
79[compare_floats_example_1]
80[compare_floats_example_2]
81[compare_floats_example_3]
82[compare_floats_example_4]
83[compare_floats_example_5]
84[compare_floats_example_6]
85
86All the above examples are contained in [@../../example/float_comparison_example.cpp float_comparison_example.cpp].
87
88[h5:small Handling Absolute Errors]
89
90Imagine we're testing the following function:
91
92 double myspecial(double x)
93 {
94 return sin(x) - sin(4 * x);
95 }
96
97This function has multiple roots, some of which are quite predicable in that both
98`sin(x)` and `sin(4x)` are zero together. Others occur because the values returned
99from those two functions precisely cancel out. At such points the relative difference
100between the true value of the function and the actual value returned may be ['arbitrarily
101large] due to [@http://en.wikipedia.org/wiki/Loss_of_significance cancellation error].
102
103In such a case, testing the function above by requiring that the values returned by
104`relative_error` or `epsilon_error` are below some threshold is pointless: the best
105we can do is to verify that the ['absolute difference] between the true
106and calculated values is below some threshold.
107
108Of course, determining what that threshold should be is often tricky,
109but a good starting point would be machine epsilon multiplied by the largest
110of the values being summed. In the example above, the largest value returned
111by `sin(whatever)` is 1, so simply using machine epsilon as the target for
112maximum absolute difference might be a good start (though in practice we may need
113a slightly higher value - some trial and error will be necessary).
114
115[endsect] [/section:float_comparison Floating-point comparison]
116
117[/
118 Copyright 2015 John Maddock and Paul A. Bristow.
119 Distributed under the Boost Software License, Version 1.0.
120 (See accompanying file LICENSE_1_0.txt or copy at
121 http://www.boost.org/LICENSE_1_0.txt).
122]