如何在C中四舍五入浮点值(如37.777779)到小数点后两位(37.78)?
当前回答
Let me first attempt to justify my reason for adding yet another answer to this question. In an ideal world, rounding is not really a big deal. However, in real systems, you may need to contend with several issues that can result in rounding that may not be what you expect. For example, you may be performing financial calculations where final results are rounded and displayed to users as 2 decimal places; these same values are stored with fixed precision in a database that may include more than 2 decimal places (for various reasons; there is no optimal number of places to keep...depends on specific situations each system must support, e.g. tiny items whose prices are fractions of a penny per unit); and, floating point computations performed on values where the results are plus/minus epsilon. I have been confronting these issues and evolving my own strategy over the years. I won't claim that I have faced every scenario or have the best answer, but below is an example of my approach so far that overcomes these issues:
假设小数点后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;
}
}
四舍五入到小数点后2位的结果可以这样表示:
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,小数点后第7位为零。
对于val = 6.8249999,结果为6.83。在这种情况下,小数点后第7位是9,使Round(val,6)函数给出预期的结果。在这种情况下,后面可能有任意数量的9。
对于val = 6.824999499999,结果为6.83。作为第一步,舍入到小数点后第8位,即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是浮点数/双精度数上所有中间计算所要维持的精度。这也适用于负值。我不知道这种方法在数学上是否适用于所有可能性。
其他回答
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 ceilf(float x); // don't forget #include <math.h> and link with -lm.
例子:
float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;
使用%。printf中的2f。它只打印2个小数点。
例子:
printf("%.2f", 37.777779);
输出:
37.77
另外,如果你使用c++,你可以创建一个这样的函数:
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位的任何double myDouble,代码如下:
std::cout << prd(myDouble,n);
printf("%.2f", 37.777779);
如果你想写入C-string:
char number[24]; // dummy size, you should take care of the size!
sprintf(number, "%.2f", 37.777779);