将数字舍入到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...
由于float
和double
精度有限, 根据编码目标,这个不正确的值可能被视为正确。
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 🙂