【发布时间】:2009-01-30 20:03:52
【问题描述】:
是否有一个函数可以在 C 中舍入一个浮点数,还是我需要自己编写?
float conver = 45.592346543;
我想将实际值四舍五入到小数点后一位,conver = 45.6。
【问题讨论】:
标签: c floating-point rounding
是否有一个函数可以在 C 中舍入一个浮点数,还是我需要自己编写?
float conver = 45.592346543;
我想将实际值四舍五入到小数点后一位,conver = 45.6。
【问题讨论】:
标签: c floating-point rounding
正如 Rob 所说,您可能只想打印浮点数到小数点后 1 位。在这种情况下,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float conver = 45.592346543;
printf("conver is %0.1f\n",conver);
return 0;
}
如果您想实际对存储的值进行四舍五入,那就有点复杂了。一方面,您的一位小数位表示很少有精确的浮点模拟。如果你只是想尽可能靠近,这样的事情可能会奏效:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float conver = 45.592346543;
printf("conver is %0.1f\n",conver);
conver = conver*10.0f;
conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
conver = conver/10.0f;
//If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
//conver = roundf(conver*10.0f)/10.0f;
printf("conver is now %f\n",conver);
return 0;
}
我怀疑第二个示例是您要查找的内容,但为了完整起见,我将其包含在内。如果您确实需要在内部以这种方式表示您的数字,而不仅仅是在输出上,请考虑改用 fixed-point representation。
【讨论】:
(conver >= (floor(conver)+0.5f)) ? ceil(conver) : floor(conver) 等同于 floor(conver+0.5f)(我认为,您的意思是 >=,而不是 >)。
conver>0f ? floor(conver+0.5f) : ceil(conver-0.5f) — 也可以处理底片。
当然,你可以使用 roundf()。如果你想四舍五入到一位小数,那么你可以这样做:roundf(10 * x) / 10
【讨论】:
#include <math.h>
double round(double x);
float roundf(float x);
不要忘记使用 -lm 链接。另请参见 ceil()、floor() 和 trunc()。
【讨论】:
只是为了概括 Rob 的回答,如果您不在输出上这样做,您仍然可以使用与sprintf() 相同的界面。
不过,我认为还有另一种方法可以做到这一点。您可以尝试使用ceil() 和floor() 进行上下舍入。一个不错的技巧是添加 0.5,因此任何超过 0.5 的内容都会向上取整,但低于 0.5 的任何内容都会向下取整。 ceil() 和 floor() 仅适用于 doubles。
编辑:另外,对于浮点数,您可以使用 truncf() 截断浮点数。同样的 +0.5 技巧应该可以进行精确的舍入。
【讨论】:
ceilf() 和 floorf() 和 roundf() 进行浮动。
要打印一个四舍五入的值,@Matt J 很好地回答了这个问题。
float x = 45.592346543;
printf("%0.1f\n", x); // 45.6
由于大多数浮点 (FP) 是基于 二进制,当数学上正确的答案是x.1, x.2, ....
将 FP 号转换为 最近 0.1 是另一回事。
溢出:首先缩放 10(或 100、1000 等)的方法可能会溢出较大的 x。
float round_tenth1(float x) {
x = x * 10.0f;
...
}
双舍入:当中间和 x*10.0f + 0.5f 向上舍入一个新整数时,添加 0.5f 然后使用 floorf(x*10.0f + 0.5f)/10.0 返回错误的结果。
// Fails to round 838860.4375 correctly, comes up with 838860.5
// 0.4499999880790710449 fails as it rounds to 0.5
float round_tenth2(float x) {
if (x < 0.0) {
return ceilf(x*10.0f + 0.5f)/10.0f;
}
return floorf(x*10.0f + 0.5f)/10.0f;
}
当float x 远大于INT_MAX 时,强制转换 到int 存在明显问题。
使用roundf() 和家人,在<math.h> 中可用是最好的方法。
float round_tenthA(float x) {
double x10 = 10.0 * x;
return (float) (round(x10)/10.0);
}
为避免使用double,只需测试数字是否需要四舍五入。
float round_tenthB(float x) {
const float limit = 1.0/FLT_EPSILON;
if (fabsf(x) < limit) {
return roundf(x*10.0f)/10.0f;
}
return x;
}
【讨论】:
有一个round() 函数,还有fround(),它将舍入到最接近的整数,以双精度表示。但这不是你想要的。
我遇到了同样的问题,写了这个:
#include <math.h>
double db_round(double value, int nsig)
/* ===============
**
** Rounds double <value> to <nsig> significant figures. Always rounds
** away from zero, so -2.6 to 1 sig fig will become -3.0.
**
** <nsig> should be in the range 1 - 15
*/
{
double a, b;
long long i;
int neg = 0;
if(!value) return value;
if(value < 0.0)
{
value = -value;
neg = 1;
}
i = nsig - log10(value);
if(i) a = pow(10.0, (double)i);
else a = 1.0;
b = value * a;
i = b + 0.5;
value = i / a;
return neg ? -value : value;
}
【讨论】:
你可以使用#define round(a) (int) (a+0.5) 作为宏 所以当你写 round(1.6) 时它返回 2 并且每当你写 round(1.3) 它返回 1。
【讨论】: