格式化float数值时精度丢失:如何得到40.432000的输出?
嘿,这个问题我太熟了——这就是float类型的精度特性搞的鬼!很多十进制小数没法被二进制浮点数精确存储,所以你存的40.432其实已经是个近似值,格式化后自然会输出40.431999这种结果。不过要得到你想要的40.432000,有几个靠谱的办法:
办法1:改用double类型存储数值
double的精度比float高得多,40.432这类数值用double存储时能更接近真实值,格式化后直接就能得到预期结果。比如:
double argument = 40.432; char buff[100]; snprintf(buff, sizeof(buff), "%f", argument); std::string result = buff; // 结果就是40.432000
用boost的写法也一样:
double argument = 40.432; std::string result = boost::str(boost::format("%f") % argument);
办法2:对float数值做四舍五入后再格式化
如果必须用float,那可以先把数值四舍五入到三位小数,再格式化输出六位小数。核心思路是放大数值后四舍五入,再缩小回去:
float argument = 40.432; char buff[100]; // 放大1000倍后四舍五入,再缩小回原比例,保证三位小数精确 snprintf(buff, sizeof(buff), "%.6f", round(argument * 1000) / 1000); std::string result = buff; // 得到40.432000
办法3:利用格式化精度控制自动四舍五入
也可以直接在格式化时通过精度设置让printf帮你完成四舍五入,不过最好先转成double避免额外精度损失:
float argument = 40.432; char buff[100]; snprintf(buff, sizeof(buff), "%.6f", static_cast<double>(round(argument * 1000)) / 1000); std::string result = buff;
本质上,float的精度只有约6-7位有效数字,没法精确表示所有十进制小数。如果你的场景对数值精度要求高,优先选double类型,能从根源上减少这种近似误差。
内容的提问来源于stack exchange,提问作者Karine
相关产品推荐
相关产品推荐

