I need to frequently compare floating-points or find their floors / ceilings, all under a predefined threshold eps
. To reduce the hustle, I wrote a small tool:
template < typename ing, typename num > // Integer type and floating-point type.
struct Float
{
num val, eps;
Float ( num val, num eps ): val(val), eps(eps) {}
ing floor()
{
ing valint = std::round(val);
return std::abs(val - valint) <= eps ? valint : std::floor(val);
}
ing ceil()
{
ing valint = std::round(val);
return std::abs(val - valint) <= eps ? valint : std::ceil(val);
}
friend bool operator < (Float && x, Float && y) { return y.val - x.val > x.eps; }
friend bool operator > (Float && x, Float && y) { return x.val - y.val > x.eps; }
friend bool operator <= (Float && x, Float && y) { return x.val - y.val <= x.eps; }
friend bool operator >= (Float && x, Float && y) { return y.val - x.val <= x.eps; }
friend bool operator == (Float && x, Float && y) { return std::abs(x.val - y.val) <= x.eps; }
};
template <typename ing, typename num>
struct CompareFloat
{
num eps;
CompareFloat(num eps): eps(eps) {}
Float<ing, num> operator()(num x) { return Float<ing, num> (x, eps); }
};
The class is intended to be used like:
void test(double eps = 1e-10)
{
CompareFloat<int, double> f(eps);
f(3.14) <= f(3.15);
f(2.9) > f(7.8);
f( (3 - 1.9) / 0.3 ).floor();
f( (3 - 1.9) / 0.3 ).ceil();
}
The idea is to just wrap any floating-point of interest in a small function, and keep everything else intact. This retains the high readability and low maintenance. Anything like f(3.14, 1e-10)
is just too much.
I don’t want anything related to static
/ global variables for thread safety reasons. Setting up a namespace and inject nonlocal variables would also be disappointing.
I am unsatisfied with my current solution. It copies eps
at least 3 times for a comparison, and makes Float
twice the size of the number of interest. I can console myself that the compiler will probably optimize the redundancy away, which is the greatest mentality towards coding.
So what is the leanest approach to what I want?
Thank you!