user1482030
user1482030

Reputation: 827

Round a double to the closest and greater float

I want to round big double number (>1e6) to the closest but bigger float using c/c++. I tried this but I'm not sure it is always correct and there is maybe a fastest way to do that :

int main() {
    // x is the double we want to round
    double x = 100000000005.0;
    double y = log10(x) - 7.0;
    float a = pow(10.0, y);
    float b = (float)x;

    //c the closest round up float
    float c = a + b;
    printf("%.12f %.12f %.12f\n", c, b, x);
    return 0;
}

Thank you.

Upvotes: 6

Views: 5370

Answers (3)

Aki Suihkonen
Aki Suihkonen

Reputation: 20017

Simply assigning a double to float and back should tell, if the float is larger. If it's not, one should simply increment the float by one unit. (for positive floats). If this doesn't still produce expected result, then the double is larger than supported by a float, in which case float should be assigned to Inf.

float next(double a) {
    float b=a;
    if ((double)b > a) return b;
    return std::nextafter(b, std::numeric_limits<float>::infinity());
}

[Hack] C-version of next_after (on selected architectures would be)

float next_after(float a) {
    *(int*)&a += a < 0 ? -1 : 1;
    return a;
}

Better way to do it is:

float next_after(float a) {
   union { float a; int b; } c = { .a = a };
   c.b += a < 0 ? -1 : 1;
   return c.a;
}

Both of these self-made hacks ignore Infs and NaNs (and work on non-negative floats only). The math is based on the fact, that the binary representations of floats are ordered. To get to next representable float, one simply increments the binary representation by one.

Upvotes: 6

Dave
Dave

Reputation: 46249

C has a nice nextafter function which will help here;

float toBiggerFloat( const double a ) {
    const float test = (float) a;
    return ((double) test < a) ? nextafterf( test, INFINITY ) : test;
}

Here's a test script which shows it on all classes of number (positive/negative, normal/subnormal, infinite, nan, -0): http://codepad.org/BQ3aqbae (it works fine on anything is the result)

Upvotes: 3

Mankka
Mankka

Reputation: 521

If you use , you can use the nextafterf function.

#include <stdio.h>
#include <math.h>
#include <float.h>

int main(){
  // x is the double we want to round
  double x=100000000005.0;

  float c = x;

  if ((double)c <= x)
    c = nextafterf(c, FLT_MAX);

  //c the closest round up float
  printf("%.12f %.12f\n",c,x);
  return 0;
}

Upvotes: 4

Related Questions