我想将双精度转换为字符串,在点后四舍五入到 2 位小数。我希望 1.009 显示为“1.01”,而 1.0 显示为“1”。这是我尝试过的:
std::ostringstream oss;
oss << std::fixed << std::setprecision(2) << std::noshowpoint << 1.0;
它输出“1.00”,即使我从未设置宽度甚至指定std::noshowpoint
. 如何实现所需的表示?
我想将双精度转换为字符串,在点后四舍五入到 2 位小数。我希望 1.009 显示为“1.01”,而 1.0 显示为“1”。这是我尝试过的:
std::ostringstream oss;
oss << std::fixed << std::setprecision(2) << std::noshowpoint << 1.0;
它输出“1.00”,即使我从未设置宽度甚至指定std::noshowpoint
. 如何实现所需的表示?
最佳解决方案:
inline double twodec(double n) { return floor(n * 100 + 0.5) / 100; }
oss << twodec(1.0) << ' ' << twodec(1.009);
讨论
来自http://www.cplusplus.com/reference/ios/fixed/(斜体字)
当 floatfield 设置为 fixed 时,浮点值使用定点表示法写入,这意味着该值在小数部分中的位数与精度字段指定的位数完全相同,并且没有指数部分。
所以,“固定”是行不通的。
也就是说,我能想到的唯一方法是:
floor(n * 100 + 0.5) / 100
),然后使用默认表示(即不指定固定或科学或精度 - 如果fixed
或scientific
有效,首先用 清除它们std::cout.unsetf(std::ios::floatfield)
)。ostringstream
,然后删除尾随 0 和任何 '.' (相当可怕)。这是我基于托尼回答的最终解决方案:
template <typename T>
std::string stringForNumber( T f, int precision /* = 0 */, bool fixedWidth /*= false*/ )
{
std::ostringstream ss;
ss.setf(std::ios_base::fixed);
if (precision > 0)
ss << std::setprecision(precision);
ss << f;
std::string str(ss.str());
if (!fixedWidth) // Removing trailing 0
{
const auto pointLocation = str.find_first_of(".,");
if (pointLocation != std::string::npos)
{
const auto lastZeroPos = str.find_last_of('0');
const auto lastNotZeroPos = str.find_last_not_of('0');
if (lastNotZeroPos == pointLocation) // Integer number
str.erase(pointLocation);
else if (lastZeroPos != std::string::npos && lastNotZeroPos != std::string::npos && pointLocation < lastZeroPos && lastNotZeroPos < lastZeroPos)
{
str.erase(lastNotZeroPos+1);
}
}
}
return str;
}