我根据通过json数据包收到的数字进行了一组浮点计算。在我的计算结束时,我要求其中一个数字为> = -0.5。我发现有时我的测试值不合格,因为它低于阈值ULP。无论如何要写一个像
这样的表达式constexpr auto threshold = -0.5 - 2*ULP;
还是我必须诉诸
之类的东西auto threshold = -0.5;
threshold = std::nexttoward(threshold, -2.0);
threshold = std::nexttoward(threshold, -2.0);
答案 0 :(得分:4)
您应该可以使用epsilon
达到所需的阈值,例如
constexpr auto threshold = -0.5 - std::numeric_limits<double>::epsilon();
如果您认为自己确实需要,可能会添加*2
,但由于epsilon
已定义为值1.0
,因此0.5
可能适合您
或者,不要将其用作constexpr
。除非它是一些性能敏感的代码中的内部循环,否则差异应该可以忽略不计:
const auto threshold = std::nexttoward(std::nexttoward( -0.5, -2.0), -2.0);
答案 1 :(得分:3)
也许这样的事情可以做到(它需要基数2浮点表示,并且它不适用于非正规数):
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();
它是如何工作的(我用IEEE754描述它)?
当数字在[1.0; 2.0]范围内时,Epsilon表示1 ULP。我们需要缩放epsilon,因此它总是意味着1 ULP。比例基于浮点数的指数部分。如果数字是[1.0; 2.0),那么比例必须是1.如果数字是[2.0; 4.0),那么比例必须是2,对于[4.0; 8.0),它必须是4,等等。所以,我们需要找到最近的,小于或等于2的幂:它是2^floor(log2(number))
。我们需要关注负数,这就是公式中abs
和(num<0?-1:1)
的原因。