将数字舍入到C中的2个小数位数

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

如果您只是为了输出目的而舍入数字,那么"%.2f"格式的string确实是正确的答案。 但是,如果您实际上想要将浮点值四舍五入以便进一步计算,则可以使用以下方法:

 #include <math.h> float val = 37.777779; float rounded_down = floorf(val * 100) / 100; /* Result: 37.77 */ float nearest = roundf(val * 100) / 100; /* Result: 37.78 */ float rounded_up = ceilf(val * 100) / 100; /* Result: 37.78 */ 

请注意,您可能需要select三种不同的舍入规则:舍入(即截断小数点后两位),四舍五入到最接近的四舍五入。 通常情况下,你想轮到最近。

正如其他几个人所指出的那样,由于浮点表示的怪癖,这些四舍五入的值可能并不完全是“明显的”十进制值,但它们将非常接近。

有关四舍五入的更多信息(特别是关于四舍五入到最近的打破规则),请参阅维基百科关于舍入的文章 。

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

假设你正在谈论印刷的价值,那么Andrew Coleson和Arak的回答是正确的:

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

但是请注意,如果您的目标是将内部使用的数字凑成37.78(例如,与其他值进行比较),那么由于浮点数的工作方式,这不是一个好主意:您通常不会想要进行浮点的等式比较,而不是使用目标值+/- sigma值。 或者将数字编码为已知精度的string,然后进行比较。

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

这个怎么样:

 float value = 37.777779; float rounded = ((int)(value * 100 + .5) / 100.0); 
 printf("%.2f", 37.777779); 

如果你想写Cstring:

 char number[24]; // dummy size, you should take care of the size! sprintf(number, "%.2f", 37.777779); 

没有办法将一个float舍入到另一个float因为舍入的float可能不能表示(浮点数的限制)。 例如,你说37.777779到37.78,但最接近的数字是37.781。

但是,您可以使用格式string函数“四舍五入” float

另外,如果你使用C ++,你可以创build一个像这样的函数:

 string prd(const double x, const int decDigits) { stringstream ss; ss << fixed; ss.precision(decDigits); // set # places after decimal ss << x; return ss.str(); } 

然后你可以用小数点后面的n位置输出任意两个myDouble ,代码如下:

 std::cout << prd(myDouble,n); 

在C ++(或用C风格转换的C语言)中,可以创build函数:

 /* Function to control # of decimal places to be output for x */ double showDecimals(const double& x, const int& numDecimals) { int y=x; double z=xy; 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。

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

你仍然可以使用:

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

例:

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

使用float roundf(float x)

“这个循环函数把它们的参数四舍五入到浮点格式的最接近的整数值,不pipe当前的舍入方向如何,都将零值从零中舍入。 C11dr§7.12.9.5

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

根据你的float实现,看起来是中途的数字不是。 因为浮点通常是基于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.120000004768... float 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... float 1.129999995232...

如果使用代码

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

虽然“1.135”在1.13和1.14之间是“中途”,但当转换为float ,值为1.134999990463... ,不再是“中途”,而是接近1.13,但错误地转为1.139999985695... float 1.139999985695...由于floatdouble精度有限, 根据编码目标,这个不正确的值可能被视为正确。

 double f_round(double dval, int n) { char l_fmtp[32], l_buf[64]; char *p_str; sprintf (l_fmtp, "%%.%df", n); if (dval>=0) sprintf (l_buf, l_fmtp, dval); else sprintf (l_buf, l_fmtp, dval); return ((double)strtod(l_buf, &p_str)); } 

这里n是小数位数

例:

 double d = 100.23456; printf("%f", f_round(d, 4));// result: 100.2346 printf("%f", f_round(d, 2));// result: 100.23 

这个函数取数字和精度并返回四舍五入的数字

 float roundoff(float num,int precision) { int temp=(int )(num*pow(10,precision)); int num1=num*pow(10,precision+1); temp*=10; temp+=5; if(num1>=temp) num1+=10; num1/=10; num1*=10; num=num1/pow(10,precision+1); return num; } 

它将浮点数转换成int,方法是左移该点并检查五个以上的条件。

试试这个。 它会给一个双精度小数点后两位。

  int ttt = round(value * 100); string str = to_string(ttt); str.insert (str.end()-2,1,'.'); double temp = ::strtod(str.c_str(), 0); obPrinciple = temp; 

假设使用下面的四舍五入函数/方法,将6位小数作为浮点数/双精度的计算(针对具体应用的任意决定)被认为是足够精确的:

 double Round(double x, int p) { if (x != 0.0) { return ((floor((fabs(x)*pow(double(10.0),p))+0.5))/pow(double(10.0),p))*(x/fabs(x)); } else { return 0.0; } } 

四舍五入到小数点后两位可显示结果,如下所示:

 double val; // ...perform calculations on val String(Round(Round(Round(val,8),6),2)); 

对于val = 6.825 ,结果如预期的那样是6.83

对于val = 6.824999 ,结果是6.82 。 这里的假设是计算结果正好是6.824999 ,小数点第七位是零。

对于val = 6.8249999 ,结果是6.83 。 在这种情况下,小数点第七位是9 ,导致Round(val,6)函数给出预期的结果。 对于这种情况,可以有任何数量的尾随9秒。

对于val = 6.824999499999 ,结果是6.83 。 作为第一步舍入到小数点后第八位,即Round(val,8)处理一个令人讨厌的情况,计算的浮点数结果计算为6.8249995 ,但在内部表示为6.824999499999...

最后,从问题的例子… val = 37.777779结果在37.78

这种方法可以进一步概括为:

 double val; // ...perform calculations on val String(Round(Round(Round(val,N+2),N),2)); 

其中N是浮点数/双精度的所有中间计算的精度。 这也适用于负值。 我不知道这种方法是否在math上正确的所有可能性。

我为这个圆形浮点数做了这个macros把它添加到你的头文件中

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

这里是一个例子:

 float x = ROUNDF(3.141592, 100) 

x等于3.14 🙂