将双精度浮点数舍入到最接近且更大的浮点数

Round a double to the closest and greater float

本文关键字:浮点数 最接近 双精度浮点数 舍入      更新时间:2023-10-16

我想使用c/c++将大双位数(>1e6)四舍五入到最接近但更大的浮点数。我试过这个,但我不确定它总是正确的,也许有一个最快的方法来做到这一点:

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 %.12fn", c, b, x);
    return 0;
}

谢谢。

简单的赋值给float和back一个double变量就可以知道float是否更大。如果不是,应该简单地将浮点数增加一个单位。(对于正浮点数)。如果这仍然不能产生预期的结果,则说明双精度数比浮点数支持的值大,在这种情况下,应该将float赋值给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版本的next_after(在选定的体系结构上将是)

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

更好的方法是:

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

这两个自制的hack都忽略了inf和nan(并且只工作于非负浮点数)。数学是基于这样一个事实,即浮点数的二进制表示是有序的。要获得下一个可表示的浮点数,只需将二进制表示形式加1。

如果使用c99,则可以使用nextafterf函数。

#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 %.12fn",c,x);
  return 0;
}

C有一个很好的nextafter函数,在这里会有帮助;

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

这是一个测试脚本,显示它在所有类的数字(正/负,正常/次正常,无限,nan, -0): http://codepad.org/BQ3aqbae(它工作得很好,任何是结果)