]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <html> |
2 | <head> | |
3 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
4 | <title>Floating-point Comparison</title> | |
5 | <link rel="stylesheet" href="../math.css" type="text/css"> | |
6 | <meta name="generator" content="DocBook XSL Stylesheets V1.77.1"> | |
7 | <link rel="home" href="../index.html" title="Math Toolkit 2.5.1"> | |
8 | <link rel="up" href="../utils.html" title="Chapter 2. Floating Point Utilities"> | |
9 | <link rel="prev" href="next_float/ulp.html" title="Obtaining the Size of a Unit In the Last Place - ULP"> | |
10 | <link rel="next" href="../cstdfloat.html" title="Chapter 3. Specified-width floating-point typedefs"> | |
11 | </head> | |
12 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | |
13 | <table cellpadding="2" width="100%"><tr> | |
14 | <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> | |
15 | <td align="center"><a href="../../../../../index.html">Home</a></td> | |
16 | <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> | |
17 | <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> | |
18 | <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> | |
19 | <td align="center"><a href="../../../../../more/index.htm">More</a></td> | |
20 | </tr></table> | |
21 | <hr> | |
22 | <div class="spirit-nav"> | |
23 | <a accesskey="p" href="next_float/ulp.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../utils.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../cstdfloat.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> | |
24 | </div> | |
25 | <div class="section"> | |
26 | <div class="titlepage"><div><div><h2 class="title" style="clear: both"> | |
27 | <a name="math_toolkit.float_comparison"></a><a class="link" href="float_comparison.html" title="Floating-point Comparison">Floating-point Comparison</a> | |
28 | </h2></div></div></div> | |
29 | <p> | |
30 | Comparison of floating-point values has always been a source of endless difficulty | |
31 | and confusion. | |
32 | </p> | |
33 | <p> | |
34 | Unlike integral values that are exact, all floating-point operations will potentially | |
35 | produce an inexact result that will be rounded to the nearest available binary | |
36 | representation. Even apparently inocuous operations such as assigning 0.1 to | |
37 | a double produces an inexact result (as this decimal number has no exact binary | |
38 | representation). | |
39 | </p> | |
40 | <p> | |
41 | Floating-point computations also involve rounding so that some 'computational | |
42 | noise' is added, and hence results are also not exact (although repeatable, | |
43 | at least under identical platforms and compile options). | |
44 | </p> | |
45 | <p> | |
46 | Sadly, this conflicts with the expectation of most users, as many articles | |
47 | and innumerable cries for help show all too well. | |
48 | </p> | |
49 | <p> | |
50 | Some background reading is: | |
51 | </p> | |
52 | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | |
53 | <li class="listitem"> | |
54 | Knuth D.E. The art of computer programming, vol II, section 4.2, especially | |
55 | Floating-Point Comparison 4.2.2, pages 198-220. | |
56 | </li> | |
57 | <li class="listitem"> | |
58 | <a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html" target="_top">David | |
59 | Goldberg, "What Every Computer Scientist Should Know About Floating-Point | |
60 | Arithmetic"</a> | |
61 | </li> | |
62 | <li class="listitem"> | |
63 | <a href="http://adtmag.com/articles/2000/03/16/comparing-floatshow-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been-r.aspx" target="_top">Alberto | |
64 | Squassabia, Comparing floats listing</a> | |
65 | </li> | |
66 | <li class="listitem"> | |
67 | <a href="https://code.google.com/p/googletest/wiki/AdvancedGuide#Floating-Point_Comparison" target="_top">Google | |
68 | Floating-Point_Comparison guide</a> | |
69 | </li> | |
70 | <li class="listitem"> | |
71 | <a href="../../../../../libs/test/doc/html/boost_test/users_guide/testing_tools/testing_floating_points.html" target="_top">Boost.Test | |
72 | Floating-Point_Comparison</a> | |
73 | </li> | |
74 | </ul></div> | |
75 | <p> | |
76 | Boost provides a number of ways to compare floating-point values to see if | |
77 | they are tolerably close enough to each other, but first we must decide what | |
78 | kind of comparison we require: | |
79 | </p> | |
80 | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | |
81 | <li class="listitem"> | |
82 | Absolute difference/error: the absolute difference between two values | |
83 | <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> is simply <code class="computeroutput"><span class="identifier">fabs</span><span class="special">(</span><span class="identifier">a</span><span class="special">-</span><span class="identifier">b</span><span class="special">)</span></code>. This is the only meaningful comparison | |
84 | to make if we know that the result may have cancellation error (see below). | |
85 | </li> | |
86 | <li class="listitem"> | |
87 | The edit distance between the two values: i.e. how many (binary) floating-point | |
88 | values are between two values <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span>? | |
89 | This is provided by the function <a href="../../../../../libs/math/doc/html/math_toolkit/next_float/float_distance.html" target="_top">Boost.Math | |
90 | float_distance</a>, but is probably only useful when you know that | |
91 | the distance should be very small. This function is somewhat difficult | |
92 | to compute, and doesn't scale to values that are very far apart. In other | |
93 | words, use with care. | |
94 | </li> | |
95 | <li class="listitem"> | |
96 | The relative distance/error between two values. This is quick and easy | |
97 | to compute, and is generally the method of choice when checking that your | |
98 | results are "tolerably close" to one another. However, it is | |
99 | not as exact as the edit distance when dealing with small differences, | |
100 | and due to the way floating-point values are encoded can "wobble" | |
101 | by a factor of 2 compared to the "true" edit distance. This is | |
102 | the method documented below: if <code class="computeroutput"><span class="identifier">float_distance</span></code> | |
103 | is a surgeon's scalpel, then <code class="computeroutput"><span class="identifier">relative_difference</span></code> | |
104 | is more like a Swiss army knife: both have important but different use | |
105 | cases. | |
106 | </li> | |
107 | </ul></div> | |
108 | <h6> | |
109 | <a name="math_toolkit.float_comparison.h0"></a> | |
110 | <span class="phrase"><a name="math_toolkit.float_comparison.fp_relative"></a></span><a class="link" href="float_comparison.html#math_toolkit.float_comparison.fp_relative">Relative | |
111 | Comparison of Floating-point Values</a> | |
112 | </h6> | |
113 | <p> | |
114 | <code class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">relative_difference</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code> | |
115 | </p> | |
116 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> | |
117 | <a class="link" href="result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">U</span> <span class="identifier">b</span><span class="special">);</span> | |
118 | ||
119 | <span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> | |
120 | <a class="link" href="result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">U</span> <span class="identifier">b</span><span class="special">);</span> | |
121 | </pre> | |
122 | <p> | |
123 | The function <code class="computeroutput"><span class="identifier">relative_difference</span></code> | |
124 | returns the relative distance/error <span class="emphasis"><em>E</em></span> between two values | |
125 | as defined by: | |
126 | </p> | |
127 | <pre class="programlisting">E = fabs((a - b) / min(a,b))</pre> | |
128 | <p> | |
129 | The function <code class="computeroutput"><span class="identifier">epsilon_difference</span></code> | |
130 | is a convenience function that returns <code class="computeroutput"><span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> | |
131 | <span class="identifier">b</span><span class="special">)</span> <span class="special">/</span> <span class="identifier">eps</span></code> where | |
132 | <code class="computeroutput"><span class="identifier">eps</span></code> is the machine epsilon | |
133 | for the result type. | |
134 | </p> | |
135 | <p> | |
136 | The following special cases are handled as follows: | |
137 | </p> | |
138 | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | |
139 | <li class="listitem"> | |
140 | If either of <span class="emphasis"><em>a</em></span> or <span class="emphasis"><em>b</em></span> is a NaN, | |
141 | then returns the largest representable value for T: for example for type | |
142 | <code class="computeroutput"><span class="keyword">double</span></code>, this is <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">double</span><span class="special">>::</span><span class="identifier">max</span><span class="special">()</span></code> | |
143 | which is the same as <code class="computeroutput"><span class="identifier">DBL_MAX</span></code> | |
144 | or <code class="computeroutput"><span class="number">1.7976931348623157e+308</span></code>. | |
145 | </li> | |
146 | <li class="listitem"> | |
147 | If <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> differ in sign then | |
148 | returns the largest representable value for T. | |
149 | </li> | |
150 | <li class="listitem"> | |
151 | If both <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> are both infinities | |
152 | (of the same sign), then returns zero. | |
153 | </li> | |
154 | <li class="listitem"> | |
155 | If just one of <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> is an | |
156 | infinity, then returns the largest representable value for T. | |
157 | </li> | |
158 | <li class="listitem"> | |
159 | If both <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> are zero then | |
160 | returns zero. | |
161 | </li> | |
162 | <li class="listitem"> | |
163 | If just one of <span class="emphasis"><em>a</em></span> or <span class="emphasis"><em>b</em></span> is a zero | |
164 | or a denormalized value, then it is treated as if it were the smallest | |
165 | (non-denormalized) value representable in T for the purposes of the above | |
166 | calculation. | |
167 | </li> | |
168 | </ul></div> | |
169 | <p> | |
170 | These rules were primarily designed to assist with our own test suite, they | |
171 | are designed to be robust enough that the function can in most cases be used | |
172 | blindly, including in cases where the expected result is actually too small | |
173 | to represent in type T and underflows to zero. | |
174 | </p> | |
175 | <h6> | |
176 | <a name="math_toolkit.float_comparison.h1"></a> | |
177 | <span class="phrase"><a name="math_toolkit.float_comparison.examples"></a></span><a class="link" href="float_comparison.html#math_toolkit.float_comparison.examples">Examples</a> | |
178 | </h6> | |
179 | <p> | |
180 | Some using statements will ensure that the functions we need are accessible. | |
181 | </p> | |
182 | <pre class="programlisting"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">;</span> | |
183 | </pre> | |
184 | <p> | |
185 | or | |
186 | </p> | |
187 | <pre class="programlisting"><span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">relative_difference</span><span class="special">;</span> | |
188 | <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">epsilon_difference</span><span class="special">;</span> | |
189 | <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">float_next</span><span class="special">;</span> | |
190 | <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">float_prior</span><span class="special">;</span> | |
191 | </pre> | |
192 | <p> | |
193 | The following examples display values with all possibly significant digits. | |
194 | Newer compilers should provide <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limitsFPT</span><span class="special">>::</span><span class="identifier">max_digits10</span></code> | |
195 | for this purpose, and here we use <code class="computeroutput"><span class="keyword">float</span></code> | |
196 | precision where <code class="computeroutput"><span class="identifier">max_digits10</span></code> | |
197 | = 9 to avoid displaying a distracting number of decimal digits. | |
198 | </p> | |
199 | <div class="note"><table border="0" summary="Note"> | |
200 | <tr> | |
201 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> | |
202 | <th align="left">Note</th> | |
203 | </tr> | |
204 | <tr><td align="left" valign="top"><p> | |
205 | Older compilers can use this formula to calculate <code class="computeroutput"><span class="identifier">max_digits10</span></code> | |
206 | from <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="identifier">FPT</span><span class="special">>::</span><span class="identifier">digits10</span></code>:<br>    <code class="computeroutput"><span class="keyword">int</span> | |
207 | <span class="identifier">max_digits10</span> <span class="special">=</span> | |
208 | <span class="number">2</span> <span class="special">+</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="identifier">FPT</span><span class="special">>::</span><span class="identifier">digits10</span> | |
209 | <span class="special">*</span> <span class="number">3010</span><span class="special">/</span><span class="number">10000</span><span class="special">;</span></code> | |
210 | </p></td></tr> | |
211 | </table></div> | |
212 | <p> | |
213 | One can set the display including all trailing zeros (helpful for this example | |
214 | to show all potentially significant digits), and also to display <code class="computeroutput"><span class="keyword">bool</span></code> values as words rather than integers: | |
215 | </p> | |
216 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">.</span><span class="identifier">precision</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">float</span><span class="special">>::</span><span class="identifier">max_digits10</span><span class="special">);</span> | |
217 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">showpoint</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
218 | </pre> | |
219 | <p> | |
220 | When comparing values that are <span class="emphasis"><em>quite close</em></span> or <span class="emphasis"><em>approximately | |
221 | equal</em></span>, we could use either <code class="computeroutput"><span class="identifier">float_distance</span></code> | |
222 | or <code class="computeroutput"><span class="identifier">relative_difference</span></code>/<code class="computeroutput"><span class="identifier">epsilon_difference</span></code>, for example with type | |
223 | <code class="computeroutput"><span class="keyword">float</span></code>, these two values are adjacent | |
224 | to each other: | |
225 | </p> | |
226 | <pre class="programlisting"><span class="keyword">float</span> <span class="identifier">a</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span> | |
227 | <span class="keyword">float</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">1</span> <span class="special">+</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">float</span><span class="special">>::</span><span class="identifier">epsilon</span><span class="special">();</span> | |
228 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a = "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
229 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b = "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
230 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"float_distance = "</span> <span class="special"><<</span> <span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
231 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
232 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"epsilon_difference = "</span> <span class="special"><<</span> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
233 | </pre> | |
234 | <p> | |
235 | Which produces the output: | |
236 | </p> | |
237 | <pre class="programlisting">a = 1.00000000 | |
238 | b = 1.00000012 | |
239 | float_distance = 1.00000000 | |
240 | relative_difference = 1.19209290e-007 | |
241 | epsilon_difference = 1.00000000 | |
242 | </pre> | |
243 | <p> | |
244 | In the example above, it just so happens that the edit distance as measured | |
245 | by <code class="computeroutput"><span class="identifier">float_distance</span></code>, and the | |
246 | difference measured in units of epsilon were equal. However, due to the way | |
247 | floating point values are represented, that is not always the case: | |
248 | </p> | |
249 | <pre class="programlisting"><span class="identifier">a</span> <span class="special">=</span> <span class="number">2.0f</span> <span class="special">/</span> <span class="number">3.0f</span><span class="special">;</span> <span class="comment">// 2/3 inexactly represented as a float</span> | |
250 | <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">float_next</span><span class="special">(</span><span class="identifier">float_next</span><span class="special">(</span><span class="identifier">float_next</span><span class="special">(</span><span class="identifier">a</span><span class="special">)));</span> <span class="comment">// 3 floating point values above a</span> | |
251 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a = "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
252 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b = "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
253 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"float_distance = "</span> <span class="special"><<</span> <span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
254 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
255 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"epsilon_difference = "</span> <span class="special"><<</span> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
256 | </pre> | |
257 | <p> | |
258 | Which produces the output: | |
259 | </p> | |
260 | <pre class="programlisting">a = 0.666666687 | |
261 | b = 0.666666865 | |
262 | float_distance = 3.00000000 | |
263 | relative_difference = 2.68220901e-007 | |
264 | epsilon_difference = 2.25000000 | |
265 | </pre> | |
266 | <p> | |
267 | There is another important difference between <code class="computeroutput"><span class="identifier">float_distance</span></code> | |
268 | and the <code class="computeroutput"><span class="identifier">relative_difference</span><span class="special">/</span><span class="identifier">epsilon_difference</span></code> | |
269 | functions in that <code class="computeroutput"><span class="identifier">float_distance</span></code> | |
270 | returns a signed result that reflects which argument is larger in magnitude, | |
271 | where as <code class="computeroutput"><span class="identifier">relative_difference</span><span class="special">/</span><span class="identifier">epsilon_difference</span></code> | |
272 | simply return an unsigned value that represents how far apart the values are. | |
273 | For example if we swap the order of the arguments: | |
274 | </p> | |
275 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"float_distance = "</span> <span class="special"><<</span> <span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
276 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
277 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"epsilon_difference = "</span> <span class="special"><<</span> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">b</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
278 | </pre> | |
279 | <p> | |
280 | The output is now: | |
281 | </p> | |
282 | <pre class="programlisting">float_distance = -3.00000000 | |
283 | relative_difference = 2.68220901e-007 | |
284 | epsilon_difference = 2.25000000 | |
285 | </pre> | |
286 | <p> | |
287 | Zeros are always treated as equal, as are infinities as long as they have the | |
288 | same sign: | |
289 | </p> | |
290 | <pre class="programlisting"><span class="identifier">a</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | |
291 | <span class="identifier">b</span> <span class="special">=</span> <span class="special">-</span><span class="number">0</span><span class="special">;</span> <span class="comment">// signed zero</span> | |
292 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
293 | <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">float</span><span class="special">>::</span><span class="identifier">infinity</span><span class="special">();</span> | |
294 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
295 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="special">-</span><span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
296 | </pre> | |
297 | <p> | |
298 | Which produces the output: | |
299 | </p> | |
300 | <pre class="programlisting">relative_difference = 0.000000000 | |
301 | relative_difference = 0.000000000 | |
302 | relative_difference = 3.40282347e+038 | |
303 | </pre> | |
304 | <p> | |
305 | Note that finite values are always infinitely far away from infinities even | |
306 | if those finite values are very large: | |
307 | </p> | |
308 | <pre class="programlisting"><span class="identifier">a</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">float</span><span class="special">>::</span><span class="identifier">max</span><span class="special">)();</span> | |
309 | <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">float</span><span class="special">>::</span><span class="identifier">infinity</span><span class="special">();</span> | |
310 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a = "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
311 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b = "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
312 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
313 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"epsilon_difference = "</span> <span class="special"><<</span> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
314 | </pre> | |
315 | <p> | |
316 | Which produces the output: | |
317 | </p> | |
318 | <pre class="programlisting">a = 3.40282347e+038 | |
319 | b = 1.#INF0000 | |
320 | relative_difference = 3.40282347e+038 | |
321 | epsilon_difference = 3.40282347e+038 | |
322 | </pre> | |
323 | <p> | |
324 | Finally, all denormalized values and zeros are treated as being effectively | |
325 | equal: | |
326 | </p> | |
327 | <pre class="programlisting"><span class="identifier">a</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">float</span><span class="special">>::</span><span class="identifier">denorm_min</span><span class="special">();</span> | |
328 | <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">*</span> <span class="number">2</span><span class="special">;</span> | |
329 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a = "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
330 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b = "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
331 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"float_distance = "</span> <span class="special"><<</span> <span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
332 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
333 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"epsilon_difference = "</span> <span class="special"><<</span> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
334 | <span class="identifier">a</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | |
335 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a = "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
336 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b = "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
337 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"float_distance = "</span> <span class="special"><<</span> <span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
338 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"relative_difference = "</span> <span class="special"><<</span> <span class="identifier">relative_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
339 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"epsilon_difference = "</span> <span class="special"><<</span> <span class="identifier">epsilon_difference</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
340 | </pre> | |
341 | <p> | |
342 | Which produces the output: | |
343 | </p> | |
344 | <pre class="programlisting">a = 1.40129846e-045 | |
345 | b = 2.80259693e-045 | |
346 | float_distance = 1.00000000 | |
347 | relative_difference = 0.000000000 | |
348 | epsilon_difference = 0.000000000 | |
349 | a = 0.000000000 | |
350 | b = 2.80259693e-045 | |
351 | float_distance = 2.00000000 | |
352 | relative_difference = 0.000000000 | |
353 | epsilon_difference = 0.000000000</pre> | |
354 | <p> | |
355 | Notice how, in the above example, two denormalized values that are a factor | |
356 | of 2 apart are none the less only one representation apart! | |
357 | </p> | |
358 | <p> | |
359 | All the above examples are contained in <a href="../../../example/float_comparison_example.cpp" target="_top">float_comparison_example.cpp</a>. | |
360 | </p> | |
361 | <h6> | |
362 | <a name="math_toolkit.float_comparison.h2"></a> | |
363 | <span class="phrase"><a name="math_toolkit.float_comparison.small"></a></span><a class="link" href="float_comparison.html#math_toolkit.float_comparison.small">Handling | |
364 | Absolute Errors</a> | |
365 | </h6> | |
366 | <p> | |
367 | Imagine we're testing the following function: | |
368 | </p> | |
369 | <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">myspecial</span><span class="special">(</span><span class="keyword">double</span> <span class="identifier">x</span><span class="special">)</span> | |
370 | <span class="special">{</span> | |
371 | <span class="keyword">return</span> <span class="identifier">sin</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">sin</span><span class="special">(</span><span class="number">4</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">);</span> | |
372 | <span class="special">}</span> | |
373 | </pre> | |
374 | <p> | |
375 | This function has multiple roots, some of which are quite predicable in that | |
376 | both <code class="computeroutput"><span class="identifier">sin</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code> and <code class="computeroutput"><span class="identifier">sin</span><span class="special">(</span><span class="number">4</span><span class="identifier">x</span><span class="special">)</span></code> are zero | |
377 | together. Others occur because the values returned from those two functions | |
378 | precisely cancel out. At such points the relative difference between the true | |
379 | value of the function and the actual value returned may be <span class="emphasis"><em>arbitrarily | |
380 | large</em></span> due to <a href="http://en.wikipedia.org/wiki/Loss_of_significance" target="_top">cancellation | |
381 | error</a>. | |
382 | </p> | |
383 | <p> | |
384 | In such a case, testing the function above by requiring that the values returned | |
385 | by <code class="computeroutput"><span class="identifier">relative_error</span></code> or <code class="computeroutput"><span class="identifier">epsilon_error</span></code> are below some threshold is | |
386 | pointless: the best we can do is to verify that the <span class="emphasis"><em>absolute difference</em></span> | |
387 | between the true and calculated values is below some threshold. | |
388 | </p> | |
389 | <p> | |
390 | Of course, determining what that threshold should be is often tricky, but a | |
391 | good starting point would be machine epsilon multiplied by the largest of the | |
392 | values being summed. In the example above, the largest value returned by <code class="computeroutput"><span class="identifier">sin</span><span class="special">(</span><span class="identifier">whatever</span><span class="special">)</span></code> is 1, so simply using machine epsilon as the | |
393 | target for maximum absolute difference might be a good start (though in practice | |
394 | we may need a slightly higher value - some trial and error will be necessary). | |
395 | </p> | |
396 | </div> | |
397 | <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> | |
398 | <td align="left"></td> | |
399 | <td align="right"><div class="copyright-footer">Copyright © 2006-2010, 2012-2014 Nikhar Agrawal, | |
400 | Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos, Hubert | |
401 | Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan Råde, Gautam Sewani, | |
402 | Benjamin Sobotta, Thijs van den Berg, Daryle Walker and Xiaogang Zhang<p> | |
403 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
404 | file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) | |
405 | </p> | |
406 | </div></td> | |
407 | </tr></table> | |
408 | <hr> | |
409 | <div class="spirit-nav"> | |
410 | <a accesskey="p" href="next_float/ulp.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../utils.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../cstdfloat.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> | |
411 | </div> | |
412 | </body> | |
413 | </html> |