util: epsilon comparison for doubles
add the usual standard implementation to compare floating point numbers based on the machine epsilon and the magnitude of the involved numbers
This commit is contained in:
parent
25f78bfa83
commit
efe97b9174
2 changed files with 35 additions and 7 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
UTIL-QUANT.hpp - helper functions to deal with division and quantisation
|
||||
UTIL-QUANT.hpp - helper functions to deal with quantisation and comparison
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
#define LIB_UTIL_QUANT_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
|
||||
|
|
@ -115,5 +117,31 @@ namespace util {
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* epsilon comparison of doubles.
|
||||
* @remarks Floating point calculations are only accurate up to a certain degree,
|
||||
* and we need to adjust for the magnitude of the involved numbers, since
|
||||
* floating point numbers are scaled by the exponent. Moreover, we need
|
||||
* to be careful with very small numbers (close to zero), where calculating
|
||||
* the difference could yield coarse grained 'subnormal' values.
|
||||
* @param ulp number of grid steps to allow for difference (default = 2).
|
||||
* Here, a 'grid step' is the smallest difference to 1.0 which can be
|
||||
* represented in floating point ('units in the last place')
|
||||
* @warning don't use this for comparison against zero, rather use an absolute epsilon then.
|
||||
* @see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||
* @see http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
|
||||
* @see https://en.wikipedia.org/wiki/Unit_in_the_last_place
|
||||
*/
|
||||
inline bool
|
||||
almostEqual (double d1, double d2, unsigned int ulp =2)
|
||||
{
|
||||
using std::fabs;
|
||||
return fabs (d1-d2) < DBL_EPSILON * fabs (d1+d2) * ulp
|
||||
|| fabs (d1-d2) < DBL_MIN; // special treatment for subnormal results
|
||||
}
|
||||
|
||||
|
||||
} // namespace util
|
||||
#endif /*UTIL_QUANT_H*/
|
||||
|
|
|
|||
|
|
@ -27,17 +27,18 @@
|
|||
#include "lib/diff/gen-node.hpp"
|
||||
#include "lib/diff/record.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/util-quant.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <utility>
|
||||
//#include <string>
|
||||
//#include <vector>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
using util::isnil;
|
||||
using util::contains;
|
||||
using util::isSameObject;
|
||||
using util::almostEqual;
|
||||
using lib::hash::LuidH;
|
||||
using lib::time::FSecs;
|
||||
using lib::time::Time;
|
||||
|
|
@ -46,7 +47,6 @@ using lib::test::randTime;
|
|||
//using std::string;
|
||||
//using std::vector;
|
||||
//using std::swap;
|
||||
using std::fabs;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ namespace test{
|
|||
|
||||
namespace {//Test fixture....
|
||||
|
||||
|
||||
const double PI = 3.14159265358979323846264338328;
|
||||
|
||||
}//(End)Test fixture
|
||||
|
||||
|
|
@ -117,8 +117,8 @@ namespace test{
|
|||
CHECK (contains (name(n1), "_CHILD_"));
|
||||
|
||||
// can optionally be named
|
||||
GenNode n2("π", 3.14159265358979323846264338328);
|
||||
CHECK (fabs (3.14159265 - n2.data.get<double>()) < 1e-5 );
|
||||
GenNode n2("π", PI);
|
||||
CHECK (almostEqual (PI, n2.data.get<double>()));
|
||||
CHECK (n2.isNamed());
|
||||
CHECK ("π" == n2.idi.getSym());
|
||||
CHECK ("π" == name(n2));
|
||||
|
|
@ -178,7 +178,7 @@ namespace test{
|
|||
CHECK ("NIL" == o3.data.get<Rec>().getType());
|
||||
CHECK (GenNode("Ψ", int64_t(42)) == o3.data.get<Rec>().get("Ψ"));
|
||||
CHECK (42L == o3.data.get<Rec>().get("Ψ").data.get<int64_t>());
|
||||
CHECK (1e-7 > fabs (3.14159265 - o3.data.get<Rec>().get("π").data.get<double>()));
|
||||
CHECK (almostEqual (PI, o3.data.get<Rec>().get("π").data.get<double>()));
|
||||
|
||||
LuidH luid;
|
||||
//Demonstration: object builder is based on the mutator mechanism for Records...
|
||||
|
|
|
|||
Loading…
Reference in a new issue