如何在 C++ 中优雅地格式化字符串,使其四舍五入到小数点后 6 位,并修剪额外的 '0' 或 '9'

Posted

技术标签:

【中文标题】如何在 C++ 中优雅地格式化字符串,使其四舍五入到小数点后 6 位,并修剪额外的 \'0\' 或 \'9\'【英文标题】:how do I elegantly format string in C++ so that it is rounded to 6 decimal places and has extra '0's or '9's trimmed如何在 C++ 中优雅地格式化字符串,使其四舍五入到小数点后 6 位,并修剪额外的 '0' 或 '9' 【发布时间】:2009-05-22 22:51:32 【问题描述】:

如何编写一个函数来格式化带有小数位的字符串,而不用尾随 0 或不必要的 9?鉴于小数是 2,这就是我所期望的:

0.999 -> 1.0
0.99 -> 0.99
1.01 -> 1.01
1.001 -> 1.0
123 -> 123.0
0 -> 0.0
0.1 -> 0.1

(如你所料的否定)

这是我目前所拥有的,但它的代码非常难看。有没有更好的方法来做到这一点?

string toStrMaxDecimals(double value, uint decimals) 
    value *= pow(10, decimals);
    value = round(value);
    value *= pow(0.1, decimals);
    string temp = boost::lexical_cast<string>(value); 
    size_t dot = temp.find('.');
    if (dot != string::npos) 
        if (temp.size() > dot + decimals + 1)
            temp.erase(dot + decimals + 1);
        if (*temp.rbegin() == '0')
            temp.erase(temp.find_last_not_of("0") + 1);
        if (*temp.rbegin() == '.')
            temp.append("0");
     else 
        temp.append(".0");
    
    return temp;

【问题讨论】:

【参考方案1】:
std::string toStrMaxDecimals(double value, int decimals)

    std::ostringstream ss;
    ss << std::fixed << std::setprecision(decimals) << value;
    std::string s = ss.str();
    if(decimals > 0 && s[s.find_last_not_of('0')] == '.') 
        s.erase(s.size() - decimals + 1);
    
    return s;

【讨论】:

这太棒了!如果明天没有人能做得更好,我会接受。我知道可以做得更好。谢谢。 我对此进行了测试,结果很接近:0.1 等于 0.10。因此,我将您的解决方案与我的解决方案合并 - 使用 ostringstream 进行舍入和字符串化,并使用我的代码清理结果。再次感谢。 不错的答案,完美。补充:不仅 还必须包含 才能使其工作。【参考方案2】:

sprintf 将比 C++ 流更容易、更具可读性和更高的性能。你不需要自己做任何舍入或修剪。 Sprintf 有这方面的标志。你可能想要类似的东西

sprintf(targetBuffer, "%.2g", floatingPointValue);

Sprintf 在 Java 中进行四舍五入,我很确定它在 C++ 中也是如此。

编辑:

对不起,我写的示例代码是为了你的例子。对于您的原始问题,将 %.2g 更改为 %.6g

编辑:

将 f 更改为 g 以抑制尾随零。

【讨论】:

关闭,谢谢,但它喜欢 2 是精度位数而不是小数位数。 0.999 -> 1 0.99 -> 0.99 1.01 -> 1 1.001 -> 1 123 -> 1.2e+02 0 -> 0 0.1 -> 0.1【参考方案3】:

您是否考虑过使用普通的旧 sprintf 进行格式化?

它不会完全满足您的需要,但如果您四舍五入到百分之一,然后将数字 sprintf 为 %f(对于浮点数)或 %lf(对于双浮点数)。

要四舍五入到第 100 位,您可以这样做 num = num + ((int)(num-((int)num))*100)/100;

【讨论】:

感谢您的回答,但我想生成我得到的输出,我认为它非常可读。 (比用户输入 0.7 并得到 0.7000000000003 好得多。)浏览 SO 后,我发现 find_last_not_of 非常有用,所以我想知道是否有人有任何其他字符串技巧。 (也转换为 int 类型会破坏使用双精度数字的目的)

以上是关于如何在 C++ 中优雅地格式化字符串,使其四舍五入到小数点后 6 位,并修剪额外的 '0' 或 '9'的主要内容,如果未能解决你的问题,请参考以下文章

js四舍五入不显示.00

在Java语言中四舍五入,使其与C#匹配

如何将双精度格式设置为四舍五入到最接近的美元的货币?

如何连接四舍五入的数字字符串python?

如何在不四舍五入的情况下在 Java 中格式化双输入?

没有四舍五入小数的树枝数字格式