如何在C中四舍五入浮点值(如37.777779)到小数点后两位(37.78)?


当前回答

使用float roundf(float x)。

舍入函数将其参数舍入为浮点格式中最接近的整数值,无论当前舍入方向如何,舍入距离为零的中间情况。C11dr§7.12.9.5

#include <math.h>
float y = roundf(x * 100.0f) / 100.0f; 

根据你的浮点数实现,看起来是一半的数字并不是。因为浮点数通常是面向2进制的。此外,在所有“中途”情况下,精确舍入到最接近0.01是最具挑战性的。

void r100(const char *s) {
  float x, y;
  sscanf(s, "%f", &x);
  y = round(x*100.0)/100.0;
  printf("%6s %.12e %.12e\n", s, x, y);
}

int main(void) {
  r100("1.115");
  r100("1.125");
  r100("1.135");
  return 0;
}

 1.115 1.115000009537e+00 1.120000004768e+00  
 1.125 1.125000000000e+00 1.129999995232e+00
 1.135 1.134999990463e+00 1.139999985695e+00

虽然“1.115”是介于1.11和1.12之间的“中间值”,但当转换为float时,其值为1.115000009537…并且不再是“半程”,而是更接近1.12,并四舍五入到最接近的浮动1.120000004768…

“1.125”是介于1.12和1.13之间的“中间值”,当转换为float时,值正好是1.125,是“中间值”。由于与偶数规则的关系,它四舍五入到1.13,并四舍五入到最接近的浮点数1.129999995232…

虽然“1.135”是介于1.13和1.14之间的“中间值”,但当转换为float时,其值为1.134999990463…并且不再是“半途”,而是更接近1.13,并舍入到最接近的浮动1.129999995232…

如果使用代码

y = roundf(x*100.0f)/100.0f;

虽然“1.135”是介于1.13和1.14之间的“中间值”,但当转换为float时,其值为1.134999990463…并且不再是“半路”,而是更接近1.13,但错误地舍入到浮动1.139999985695…由于浮点数和双精度数的精度更有限。这个不正确的值可能被视为正确的,这取决于编码目标。

其他回答

这个宏用于浮点数四舍五入。 把它添加到你的头文件中

#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))

这里有一个例子:

float x = ROUNDF(3.141592, 100)

X = 3.14:)

在c++中(或在带有C风格强制类型转换的C中),您可以创建以下函数:

/* Function to control # of decimal places to be output for x */
double showDecimals(const double& x, const int& numDecimals) {
    int y=x;
    double z=x-y;
    double m=pow(10,numDecimals);
    double q=z*m;
    double r=round(q);

    return static_cast<double>(y)+(1.0/m)*r;
}

然后std::cout << showDecimals(37.777779,2);结果是:37.78。

显然,你不需要在函数中创建所有5个变量,但我把它们留在那里,这样你就可以看到逻辑。可能有更简单的解决方案,但这对我来说很有效——特别是因为它允许我根据需要调整小数点后的位数。

你仍然可以使用:

float ceilf(float x); // don't forget #include <math.h> and link with -lm.

例子:

float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;

假设你谈论的是打印的值,那么Andrew Coleson和AraK的答案是正确的:

printf("%.2f", 37.777779);

但请注意,如果你的目标是将数字四舍五入到37.78以供内部使用(例如与另一个值进行比较),那么这不是一个好主意,因为浮点数的工作方式:你通常不想对浮点数进行相等比较,而是使用一个目标值+/-一个sigma值。或者将数字编码为具有已知精度的字符串,并进行比较。

请参阅Greg Hewgill对相关问题的回答中的链接,其中还涵盖了为什么不应该使用浮点数进行财务计算。

使用float roundf(float x)。

舍入函数将其参数舍入为浮点格式中最接近的整数值,无论当前舍入方向如何,舍入距离为零的中间情况。C11dr§7.12.9.5

#include <math.h>
float y = roundf(x * 100.0f) / 100.0f; 

根据你的浮点数实现,看起来是一半的数字并不是。因为浮点数通常是面向2进制的。此外,在所有“中途”情况下,精确舍入到最接近0.01是最具挑战性的。

void r100(const char *s) {
  float x, y;
  sscanf(s, "%f", &x);
  y = round(x*100.0)/100.0;
  printf("%6s %.12e %.12e\n", s, x, y);
}

int main(void) {
  r100("1.115");
  r100("1.125");
  r100("1.135");
  return 0;
}

 1.115 1.115000009537e+00 1.120000004768e+00  
 1.125 1.125000000000e+00 1.129999995232e+00
 1.135 1.134999990463e+00 1.139999985695e+00

虽然“1.115”是介于1.11和1.12之间的“中间值”,但当转换为float时,其值为1.115000009537…并且不再是“半程”,而是更接近1.12,并四舍五入到最接近的浮动1.120000004768…

“1.125”是介于1.12和1.13之间的“中间值”,当转换为float时,值正好是1.125,是“中间值”。由于与偶数规则的关系,它四舍五入到1.13,并四舍五入到最接近的浮点数1.129999995232…

虽然“1.135”是介于1.13和1.14之间的“中间值”,但当转换为float时,其值为1.134999990463…并且不再是“半途”,而是更接近1.13,并舍入到最接近的浮动1.129999995232…

如果使用代码

y = roundf(x*100.0f)/100.0f;

虽然“1.135”是介于1.13和1.14之间的“中间值”,但当转换为float时,其值为1.134999990463…并且不再是“半路”,而是更接近1.13,但错误地舍入到浮动1.139999985695…由于浮点数和双精度数的精度更有限。这个不正确的值可能被视为正确的,这取决于编码目标。