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