如何将浮点数舍入到C中最接近的整数?

web*_*ius 7 c rounding

有没有办法在C中舍入数字?

我不想使用ceil和地板.还有其他选择吗?

当我用Google搜索答案时,我遇到了这段代码:

(int)(num < 0 ? (num - 0.5) : (num + 0.5))
Run Code Online (Sandbox Code Playgroud)

即使float num = 4.9,上面的行总是将值打印为4.

chu*_*ica 13

在C中对a进行舍入float,有3个<math.h>函数可以满足需要。推荐rintf()

\n\n
float nearbyintf(float x);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

这些nearbyint函数使用当前舍入方向将其参数舍入为浮点格式的整数值,并且不提高 \xe2\x80\x98\xe2\x80\x98inexact\xe2\x80\x99\xe2\x80\x99 浮点数例外。C11dr \xc2\xa77.12.9.3 2

\n
\n\n

或者

\n\n
float rintf(float x);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

这些rint函数与nearbyint函数 (7.12.9.3) 的不同之处仅在于,rint如果结果为,则函数可能会引发 \xe2\x80\x98\xe2\x80\x98inexact\xe2\x80\x99\xe2\x80\x99 浮点异常与参数的值不同。C11dr \xc2\xa77.12.9.4 2

\n
\n\n

或者

\n\n
float roundf(float x);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

round函数将其参数舍入为最接近的浮点格式整数值,将中间情况舍入到远离零的位置,无论当前舍入方向如何。C11dr \xc2\xa77.12.9.6 2

\n
\n\n
\n\n

例子

\n\n
#include <fenv.h>\n#include <math.h>\n#include <stdio.h>\n\nvoid rtest(const char *fname, double (*f)(double x), double x) {\n  printf("Clear inexact flag       :%s\\n", feclearexcept(FE_INEXACT) ? "Fail" : "Success");\n  printf("Set round to nearest mode:%s\\n", fesetround(FE_TONEAREST)  ? "Fail" : "Success");\n\n  double y = (*f)(x);\n  printf("%s(%f) -->  %f\\n", fname,x,y);\n\n  printf("Inexact flag             :%s\\n", fetestexcept(FE_INEXACT) ? "Inexact" : "Exact");\n  puts("");\n}\n\nint main(void) {\n  double x = 8.5;\n  rtest("nearbyint", nearbyint, x);\n  rtest("rint", rint, x);\n  rtest("round", round, x);\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出

\n\n
Clear inexact flag       :Success\nSet round to nearest mode:Success\nnearbyint(8.500000) -->  8.000000\nInexact flag             :Exact\n\nClear inexact flag       :Success\nSet round to nearest mode:Success\nrint(8.500000) -->  8.000000\nInexact flag             :Inexact\n\nClear inexact flag       :Success\nSet round to nearest mode:Success\nround(8.500000) -->  9.000000\nInexact flag             :Exact\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

OP 的代码有什么弱点?

\n\n
(int)(num < 0 ? (num - 0.5) : (num + 0.5))\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  1. 如果num值不接近该int范围,则转换(int)会导致未定义的行为。

  2. \n
  3. num +/- 0.5导致答案不准确时。这在这里不太可能,因为0.5adouble会导致加法以比 更高的精度发生float。当num0.5具有相同的精度时,0.5与数字相加可能会得到数字四舍五入的结果。(这不是 OP 帖子的整数四舍五入。)示例:根据 OP 的目标,略小于 0.5 的数字应四舍五入为 0,但会得到 1.0 和略小于 1.0 的num + 0.5最小值之间的精确答案double。由于确切的答案无法表示,因此总和通常会四舍五入到 1.0,从而导致错误的答案。类似的情况也会发生在大量的情况下。

  4. \n
\n\n
\n\n

OP 的困境是“即使在 时,上面的行也始终将值打印为 4 float num =4.9”。是无法解释的。需要额外的代码/信息。我怀疑OP可能用过int num = 4.9;.

\n\n
\n\n
// avoid all library calls\n// Relies on UINTMAX_MAX >= FLT_MAX_CONTINUOUS_INTEGER - 1\nfloat my_roundf(float x) {\n  // Test for large values of x \n  // All of the x values are whole numbers and need no rounding\n  #define FLT_MAX_CONTINUOUS_INTEGER  (FLT_RADIX/FLT_EPSILON)\n  if (x >= FLT_MAX_CONTINUOUS_INTEGER) return x;\n  if (x <= -FLT_MAX_CONTINUOUS_INTEGER) return x;\n\n  // Positive numbers\n  // Important: _no_ precision lost in the subtraction\n  // This is the key improvement over OP\'s method\n  if (x > 0) {\n    float floor_x = (float)(uintmax_t) x;\n    if (x - floor_x >= 0.5) floor_x += 1.0f;\n    return floor_x;\n  }\n\n  if (x < 0) return -my_roundf(-x);\n  return x; //  x is 0.0, -0.0 or NaN\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

测试很少——稍后当我有时间的时候会这样做。

\n


Mar*_*tos 9

4.9 + 0.5是5.4,除非编译器严重损坏,否则不能四舍五入到4.

我刚刚确认Google搜索代码给出了4.9的正确答案.

marcelo@macbookpro-1:~$ cat round.c 
#include <stdio.h>

int main() {
    float num = 4.9;
    int n = (int)(num < 0 ? (num - 0.5) : (num + 0.5));
    printf("%d\n", n);
}
marcelo@macbookpro-1:~$ make round && ./round
cc     round.c   -o round
5
marcelo@macbookpro-1:~$
Run Code Online (Sandbox Code Playgroud)

  • 这会通过 ./gcc -frip-fabric-of-space-time 生成 4。emacs 有一个插件默认打开此功能。 (2认同)

Pup*_*ppy 5

我不确定这是个好主意。该代码取决于强制转换,我很确定确切的截断是未定义的。

float result = (num - floor(num) > 0.5) ? ceil(num) : floor(num);
Run Code Online (Sandbox Code Playgroud)

我会说这是一个更好的方法(这基本上是 Shiroko 发布的),因为它不依赖于任何演员表。