Can I write a const double expression that is two ulps less than -0.5

I have a set of floating point calculations based on the numbers that I get through a json package. At the end of my calculation, I need one of the numbers to be> = -0.5. I find that sometimes I have a value that fails because it is one

+5
source share
2 answers

Maybe something like this can do this (it requires a base 2 floating point view, and it does not 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 considering IEEE754)?

Epsilon means 1 ULP when the 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 exponential part of the floating point number. If the number is [1.0; 2.0), then the scale should be 1. If the number is [2.0; 4.0], then the scale should be equal to 2, for [4.0; 8.0) it should be 4, etc. So, we need to find the nearest, lesser or equal power of 2: this is 2^floor(log2(number)) . And we need to take care of negative numbers, why abs and (num<0?-1:1) in the formula.

+3
source

You should be able to reach your desired threshold using epsilon , something like

 constexpr auto threshold = -0.5 - std::numeric_limits<double>::epsilon(); 

Perhaps add *2 if you think you really need it, although since epsilon defined for 1.0 , it might work just for you here for 0.5 .


Alternatively, just do not use it as constexpr . If this is not some kind of 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); 
+4
source

Source: https://habr.com/ru/post/1270679/


All Articles