I have a set of floating point calculation based on numbers I receive via a json packet. At the end of my calculation I require one of the numbers to be >= -0.5. I'm finding that sometimes I have a value that fails the test because it is one ULP below the threshold. Is there anyway to write a constexpression that means something like
constexpr auto threshold = -0.5 - 2*ULP;
or do I have to resort to something like
auto threshold = -0.5;
threshold = std::nexttoward(threshold, -2.0);
threshold = std::nexttoward(threshold, -2.0);
You should be able to achieve desired threshold with epsilon
, something like
constexpr auto threshold = -0.5 - std::numeric_limits<double>::epsilon();
Possibly add *2
if you think you really need it, though since epsilon
is defined for value 1.0
, it might work out just right for you here for 0.5
.
Alternatively, just don't use it as constexpr
. Unless it is some inner loop in some very performance sensitive code, the difference should be negligible:
const auto threshold = std::nexttoward(std::nexttoward( -0.5, -2.0), -2.0);
Maybe something like this can do it (it needs base 2 floating point representation, and it doesn't work for denormals):
constexpr double num = -0.5;
constexpr double threshold = num +
2.0
* (num < 0 ? -1 : 1)
* std::pow(2.0,
std::floor(std::log(std::abs(num)) / std::log(2.0)))
* std::numeric_limits<double>::epsilon();
How does it work (I describe it with IEEE754 in mind)?
Epsilon means 1 ULP when a number is in the range of [1.0;2.0). We need to scale epsilon, so it always means 1 ULP. The scale is based on the exponent part of the floating point number. If the number is [1.0;2.0), then the scale must be 1. If the number is [2.0;4.0), then the scale must be 2, for [4.0;8.0), it must be 4, etc. So, we need to find the nearest, less-than-or-equal power of 2: it is 2^floor(log2(number))
. And we need to care of negative numbers, that's why the abs
and (num<0?-1:1)
in the formula.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With