mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 18:10:21 -04:00 
			
		
		
		
	
		
			
	
	
		
			414 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
		
		
			
		
	
	
			414 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
|  | <html> | ||
|  | <head> | ||
|  | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | ||
|  | <title>Floating-point Comparison</title> | ||
|  | <link rel="stylesheet" href="../math.css" type="text/css"> | ||
|  | <meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> | ||
|  | <link rel="home" href="../index.html" title="Math Toolkit 2.5.1"> | ||
|  | <link rel="up" href="../utils.html" title="Chapter 2. Floating Point Utilities"> | ||
|  | <link rel="prev" href="next_float/ulp.html" title="Obtaining the Size of a Unit In the Last Place - ULP"> | ||
|  | <link rel="next" href="../cstdfloat.html" title="Chapter 3. Specified-width floating-point typedefs"> | ||
|  | </head> | ||
|  | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
|  | <table cellpadding="2" width="100%"><tr> | ||
|  | <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> | ||
|  | <td align="center"><a href="../../../../../index.html">Home</a></td> | ||
|  | <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> | ||
|  | <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> | ||
|  | <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> | ||
|  | <td align="center"><a href="../../../../../more/index.htm">More</a></td> | ||
|  | </tr></table> | ||
|  | <hr> | ||
|  | <div class="spirit-nav"> | ||
|  | <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> | ||
|  | </div> | ||
|  | <div class="section"> | ||
|  | <div class="titlepage"><div><div><h2 class="title" style="clear: both"> | ||
|  | <a name="math_toolkit.float_comparison"></a><a class="link" href="float_comparison.html" title="Floating-point Comparison">Floating-point Comparison</a> | ||
|  | </h2></div></div></div> | ||
|  | <p> | ||
|  |       Comparison of floating-point values has always been a source of endless difficulty | ||
|  |       and confusion. | ||
|  |     </p> | ||
|  | <p> | ||
|  |       Unlike integral values that are exact, all floating-point operations will potentially | ||
|  |       produce an inexact result that will be rounded to the nearest available binary | ||
|  |       representation. Even apparently inocuous operations such as assigning 0.1 to | ||
|  |       a double produces an inexact result (as this decimal number has no exact binary | ||
|  |       representation). | ||
|  |     </p> | ||
|  | <p> | ||
|  |       Floating-point computations also involve rounding so that some 'computational | ||
|  |       noise' is added, and hence results are also not exact (although repeatable, | ||
|  |       at least under identical platforms and compile options). | ||
|  |     </p> | ||
|  | <p> | ||
|  |       Sadly, this conflicts with the expectation of most users, as many articles | ||
|  |       and innumerable cries for help show all too well. | ||
|  |     </p> | ||
|  | <p> | ||
|  |       Some background reading is: | ||
|  |     </p> | ||
|  | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | ||
|  | <li class="listitem"> | ||
|  |           Knuth D.E. The art of computer programming, vol II, section 4.2, especially | ||
|  |           Floating-Point Comparison 4.2.2, pages 198-220. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           <a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html" target="_top">David | ||
|  |           Goldberg, "What Every Computer Scientist Should Know About Floating-Point | ||
|  |           Arithmetic"</a> | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           <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 | ||
|  |           Squassabia, Comparing floats listing</a> | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           <a href="https://code.google.com/p/googletest/wiki/AdvancedGuide#Floating-Point_Comparison" target="_top">Google | ||
|  |           Floating-Point_Comparison guide</a> | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           <a href="../../../../../libs/test/doc/html/boost_test/users_guide/testing_tools/testing_floating_points.html" target="_top">Boost.Test | ||
|  |           Floating-Point_Comparison</a> | ||
|  |         </li> | ||
|  | </ul></div> | ||
|  | <p> | ||
|  |       Boost provides a number of ways to compare floating-point values to see if | ||
|  |       they are tolerably close enough to each other, but first we must decide what | ||
|  |       kind of comparison we require: | ||
|  |     </p> | ||
|  | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | ||
|  | <li class="listitem"> | ||
|  |           Absolute difference/error: the absolute difference between two values | ||
|  |           <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 | ||
|  |           to make if we know that the result may have cancellation error (see below). | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           The edit distance between the two values: i.e. how many (binary) floating-point | ||
|  |           values are between two values <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span>? | ||
|  |           This is provided by the function <a href="../../../../../libs/math/doc/html/math_toolkit/next_float/float_distance.html" target="_top">Boost.Math | ||
|  |           float_distance</a>, but is probably only useful when you know that | ||
|  |           the distance should be very small. This function is somewhat difficult | ||
|  |           to compute, and doesn't scale to values that are very far apart. In other | ||
|  |           words, use with care. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           The relative distance/error between two values. This is quick and easy | ||
|  |           to compute, and is generally the method of choice when checking that your | ||
|  |           results are "tolerably close" to one another. However, it is | ||
|  |           not as exact as the edit distance when dealing with small differences, | ||
|  |           and due to the way floating-point values are encoded can "wobble" | ||
|  |           by a factor of 2 compared to the "true" edit distance. This is | ||
|  |           the method documented below: if <code class="computeroutput"><span class="identifier">float_distance</span></code> | ||
|  |           is a surgeon's scalpel, then <code class="computeroutput"><span class="identifier">relative_difference</span></code> | ||
|  |           is more like a Swiss army knife: both have important but different use | ||
|  |           cases. | ||
|  |         </li> | ||
|  | </ul></div> | ||
|  | <h6> | ||
|  | <a name="math_toolkit.float_comparison.h0"></a> | ||
|  |       <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 | ||
|  |       Comparison of Floating-point Values</a> | ||
|  |     </h6> | ||
|  | <p> | ||
|  |       <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> | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | 
 | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       The function <code class="computeroutput"><span class="identifier">relative_difference</span></code> | ||
|  |       returns the relative distance/error <span class="emphasis"><em>E</em></span> between two values | ||
|  |       as defined by: | ||
|  |     </p> | ||
|  | <pre class="programlisting">E = fabs((a - b) / min(a,b))</pre> | ||
|  | <p> | ||
|  |       The function <code class="computeroutput"><span class="identifier">epsilon_difference</span></code> | ||
|  |       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> | ||
|  |       <span class="identifier">b</span><span class="special">)</span> <span class="special">/</span> <span class="identifier">eps</span></code> where | ||
|  |       <code class="computeroutput"><span class="identifier">eps</span></code> is the machine epsilon | ||
|  |       for the result type. | ||
|  |     </p> | ||
|  | <p> | ||
|  |       The following special cases are handled as follows: | ||
|  |     </p> | ||
|  | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | ||
|  | <li class="listitem"> | ||
|  |           If either of <span class="emphasis"><em>a</em></span> or <span class="emphasis"><em>b</em></span> is a NaN, | ||
|  |           then returns the largest representable value for T: for example for type | ||
|  |           <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> | ||
|  |           which is the same as <code class="computeroutput"><span class="identifier">DBL_MAX</span></code> | ||
|  |           or <code class="computeroutput"><span class="number">1.7976931348623157e+308</span></code>. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           If <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> differ in sign then | ||
|  |           returns the largest representable value for T. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           If both <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> are both infinities | ||
|  |           (of the same sign), then returns zero. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           If just one of <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> is an | ||
|  |           infinity, then returns the largest representable value for T. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           If both <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> are zero then | ||
|  |           returns zero. | ||
|  |         </li> | ||
|  | <li class="listitem"> | ||
|  |           If just one of <span class="emphasis"><em>a</em></span> or <span class="emphasis"><em>b</em></span> is a zero | ||
|  |           or a denormalized value, then it is treated as if it were the smallest | ||
|  |           (non-denormalized) value representable in T for the purposes of the above | ||
|  |           calculation. | ||
|  |         </li> | ||
|  | </ul></div> | ||
|  | <p> | ||
|  |       These rules were primarily designed to assist with our own test suite, they | ||
|  |       are designed to be robust enough that the function can in most cases be used | ||
|  |       blindly, including in cases where the expected result is actually too small | ||
|  |       to represent in type T and underflows to zero. | ||
|  |     </p> | ||
|  | <h6> | ||
|  | <a name="math_toolkit.float_comparison.h1"></a> | ||
|  |       <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> | ||
|  |     </h6> | ||
|  | <p> | ||
|  |       Some using statements will ensure that the functions we need are accessible. | ||
|  |     </p> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       or | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       The following examples display values with all possibly significant digits. | ||
|  |       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> | ||
|  |       for this purpose, and here we use <code class="computeroutput"><span class="keyword">float</span></code> | ||
|  |       precision where <code class="computeroutput"><span class="identifier">max_digits10</span></code> | ||
|  |       = 9 to avoid displaying a distracting number of decimal digits. | ||
|  |     </p> | ||
|  | <div class="note"><table border="0" summary="Note"> | ||
|  | <tr> | ||
|  | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> | ||
|  | <th align="left">Note</th> | ||
|  | </tr> | ||
|  | <tr><td align="left" valign="top"><p> | ||
|  |         Older compilers can use this formula to calculate <code class="computeroutput"><span class="identifier">max_digits10</span></code> | ||
|  |         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> | ||
|  |         <span class="identifier">max_digits10</span> <span class="special">=</span> | ||
|  |         <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> | ||
|  |         <span class="special">*</span> <span class="number">3010</span><span class="special">/</span><span class="number">10000</span><span class="special">;</span></code> | ||
|  |       </p></td></tr> | ||
|  | </table></div> | ||
|  | <p> | ||
|  |       One can set the display including all trailing zeros (helpful for this example | ||
|  |       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: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       When comparing values that are <span class="emphasis"><em>quite close</em></span> or <span class="emphasis"><em>approximately | ||
|  |       equal</em></span>, we could use either <code class="computeroutput"><span class="identifier">float_distance</span></code> | ||
|  |       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 | ||
|  |       <code class="computeroutput"><span class="keyword">float</span></code>, these two values are adjacent | ||
|  |       to each other: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Which produces the output: | ||
|  |     </p> | ||
|  | <pre class="programlisting">a = 1.00000000 | ||
|  | b = 1.00000012 | ||
|  | float_distance = 1.00000000 | ||
|  | relative_difference = 1.19209290e-007 | ||
|  | epsilon_difference = 1.00000000 | ||
|  | </pre> | ||
|  | <p> | ||
|  |       In the example above, it just so happens that the edit distance as measured | ||
|  |       by <code class="computeroutput"><span class="identifier">float_distance</span></code>, and the | ||
|  |       difference measured in units of epsilon were equal. However, due to the way | ||
|  |       floating point values are represented, that is not always the case: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Which produces the output: | ||
|  |     </p> | ||
|  | <pre class="programlisting">a = 0.666666687 | ||
|  | b = 0.666666865 | ||
|  | float_distance = 3.00000000 | ||
|  | relative_difference = 2.68220901e-007 | ||
|  | epsilon_difference = 2.25000000 | ||
|  | </pre> | ||
|  | <p> | ||
|  |       There is another important difference between <code class="computeroutput"><span class="identifier">float_distance</span></code> | ||
|  |       and the <code class="computeroutput"><span class="identifier">relative_difference</span><span class="special">/</span><span class="identifier">epsilon_difference</span></code> | ||
|  |       functions in that <code class="computeroutput"><span class="identifier">float_distance</span></code> | ||
|  |       returns a signed result that reflects which argument is larger in magnitude, | ||
|  |       where as <code class="computeroutput"><span class="identifier">relative_difference</span><span class="special">/</span><span class="identifier">epsilon_difference</span></code> | ||
|  |       simply return an unsigned value that represents how far apart the values are. | ||
|  |       For example if we swap the order of the arguments: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       The output is now: | ||
|  |     </p> | ||
|  | <pre class="programlisting">float_distance = -3.00000000 | ||
|  | relative_difference = 2.68220901e-007 | ||
|  | epsilon_difference = 2.25000000 | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Zeros are always treated as equal, as are infinities as long as they have the | ||
|  |       same sign: | ||
|  |     </p> | ||
|  | <pre class="programlisting"><span class="identifier">a</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Which produces the output: | ||
|  |     </p> | ||
|  | <pre class="programlisting">relative_difference = 0.000000000 | ||
|  | relative_difference = 0.000000000 | ||
|  | relative_difference = 3.40282347e+038 | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Note that finite values are always infinitely far away from infinities even | ||
|  |       if those finite values are very large: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Which produces the output: | ||
|  |     </p> | ||
|  | <pre class="programlisting">a = 3.40282347e+038 | ||
|  | b = 1.#INF0000 | ||
|  | relative_difference = 3.40282347e+038 | ||
|  | epsilon_difference = 3.40282347e+038 | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Finally, all denormalized values and zeros are treated as being effectively | ||
|  |       equal: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <span class="identifier">a</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | <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> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       Which produces the output: | ||
|  |     </p> | ||
|  | <pre class="programlisting">a = 1.40129846e-045 | ||
|  | b = 2.80259693e-045 | ||
|  | float_distance = 1.00000000 | ||
|  | relative_difference = 0.000000000 | ||
|  | epsilon_difference = 0.000000000 | ||
|  | a = 0.000000000 | ||
|  | b = 2.80259693e-045 | ||
|  | float_distance = 2.00000000 | ||
|  | relative_difference = 0.000000000 | ||
|  | epsilon_difference = 0.000000000</pre> | ||
|  | <p> | ||
|  |       Notice how, in the above example, two denormalized values that are a factor | ||
|  |       of 2 apart are none the less only one representation apart! | ||
|  |     </p> | ||
|  | <p> | ||
|  |       All the above examples are contained in <a href="../../../example/float_comparison_example.cpp" target="_top">float_comparison_example.cpp</a>. | ||
|  |     </p> | ||
|  | <h6> | ||
|  | <a name="math_toolkit.float_comparison.h2"></a> | ||
|  |       <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 | ||
|  |       Absolute Errors</a> | ||
|  |     </h6> | ||
|  | <p> | ||
|  |       Imagine we're testing the following function: | ||
|  |     </p> | ||
|  | <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> | ||
|  | <span class="special">{</span> | ||
|  |    <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> | ||
|  | <span class="special">}</span> | ||
|  | </pre> | ||
|  | <p> | ||
|  |       This function has multiple roots, some of which are quite predicable in that | ||
|  |       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 | ||
|  |       together. Others occur because the values returned from those two functions | ||
|  |       precisely cancel out. At such points the relative difference between the true | ||
|  |       value of the function and the actual value returned may be <span class="emphasis"><em>arbitrarily | ||
|  |       large</em></span> due to <a href="http://en.wikipedia.org/wiki/Loss_of_significance" target="_top">cancellation | ||
|  |       error</a>. | ||
|  |     </p> | ||
|  | <p> | ||
|  |       In such a case, testing the function above by requiring that the values returned | ||
|  |       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 | ||
|  |       pointless: the best we can do is to verify that the <span class="emphasis"><em>absolute difference</em></span> | ||
|  |       between the true and calculated values is below some threshold. | ||
|  |     </p> | ||
|  | <p> | ||
|  |       Of course, determining what that threshold should be is often tricky, but a | ||
|  |       good starting point would be machine epsilon multiplied by the largest of the | ||
|  |       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 | ||
|  |       target for maximum absolute difference might be a good start (though in practice | ||
|  |       we may need a slightly higher value - some trial and error will be necessary). | ||
|  |     </p> | ||
|  | </div> | ||
|  | <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> | ||
|  | <td align="left"></td> | ||
|  | <td align="right"><div class="copyright-footer">Copyright © 2006-2010, 2012-2014 Nikhar Agrawal, | ||
|  |       Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos, Hubert | ||
|  |       Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan Råde, Gautam Sewani, | ||
|  |       Benjamin Sobotta, Thijs van den Berg, Daryle Walker and Xiaogang Zhang<p> | ||
|  |         Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
|  |         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>) | ||
|  |       </p> | ||
|  | </div></td> | ||
|  | </tr></table> | ||
|  | <hr> | ||
|  | <div class="spirit-nav"> | ||
|  | <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> | ||
|  | </div> | ||
|  | </body> | ||
|  | </html> |