Finding the closest floating point value less than a specific integer value in C++?

佐手、 提交于 2019-11-29 17:18:38

I'm hoping there's a magic instruction I'm not aware of that I can use to achieve this!

If you've got a C++11 (or C99) standard library, then std::nextafter(value, 0.0f) from <cmath> (or nextafter from <math.h>) will give you the largest representable value smaller than value.

It gives the "next" distinct value after the first argument, in the direction of the second; so here, the next distinct value closer to zero.

Sorry for the confusion, I've missed the point at the first time. What you are looking for is of course unit in the last place (ULP), which is closely related to machine epsilon. Here is the demo:

#include <iostream>
#include <cmath>
#include <cassert>

float compute_eps() {
  float eps = 1.0f;

  // Explicit cast to `float` is needed to
  // avoid possible extra precision pitfalls.
  while (float(1.0f + eps) != 1.0f)
    eps /= 2.0f;

  return eps;
}

float ulp(float x) {
  int exp;

  frexp(x, &exp);

  static float eps = compute_eps();

  return eps * (1 << exp);
}

main() {
  float x = 100.0f;
  float y = x - ulp(x);
  float z = nextafterf(x, 0.0f);

  assert(y == z);

  std::cout.precision(20);
  std::cout << y << std::endl;
  std::cout << z << std::endl;
}

Please, understand that this answer was intended more as educational rather than practical. I wanted to show which quantities (from theory) have to be involved in order to determine neighbouring floating-point numbers. Of course one could use std::numeric_limits<T>::epsilon() to determine machine epsilon, for example. Or go ahead and use the bullet-proof nextafterf (which is likely to be implemented much more efficiently than my demo) to directly get the neighbouring floating-point number. All in all, don't judge this answer too seriously.

NOTE: Special cases of exponent (like NaN, infinity, subnormal, and etc.) are not handled in this demo. But it's pretty straightforward how to extend this demo to support them.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!