如何在C中四舍五入浮点值(如37.777779)到小数点后两位(37.78)?
当前回答
没有办法将一个浮点数四舍五入为另一个浮点数,因为四舍五入的浮点数可能不可表示(浮点数的限制)。例如,假设你将37.777779四舍五入为37.78,但最接近的数字是37.781。
然而,你可以使用格式化字符串函数来“舍入”浮点数。
其他回答
在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个变量,但我把它们留在那里,这样你就可以看到逻辑。可能有更简单的解决方案,但这对我来说很有效——特别是因为它允许我根据需要调整小数点后的位数。
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是浮点数/双精度数上所有中间计算所要维持的精度。这也适用于负值。我不知道这种方法在数学上是否适用于所有可能性。
...或者你也可以采用传统的方式,不需要任何库:
float a = 37.777779;
int b = a; // b = 37
float c = a - b; // c = 0.777779
c *= 100; // c = 77.777863
int d = c; // d = 77;
a = b + d / (float)100; // a = 37.770000;
当然,如果你想从数字中去除额外的信息。
代码定义:
#define roundz(x,d) ((floor(((x)*pow(10,d))+.5))/pow(10,d))
结果:
a = 8.000000
sqrt(a) = r = 2.828427
roundz(r,2) = 2.830000
roundz(r,3) = 2.828000
roundz(r,5) = 2.828430
另外,如果你使用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);