我可以编写const表达式double,它是两个小于-0.5的ulps

时间:2017-08-08 12:56:13

标签: c++ floating-point floating-accuracy

我根据通过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);

2 个答案:

答案 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)的原因。