我如何在C ++中优雅地格式化字符串,以便将其四舍五入到6位小数并且具有额外的'0'或'9'被修剪

时间:2023-01-14 16:05:56

How do I write a function that formats a string with decimals digits, without trailing 0's or unnecessary 9's? Given that decimals is 2, here's what I expect:

如何编写一个格式化带小数位数字符串的函数,而不是尾随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

(negatives as you'd expect)

(你期望的负面影响)

Here's what I have so far, but it's pretty ugly code. Is there a nicer way to do this?

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

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;
}

3 个解决方案

#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;
}

#2


sprintf is going to be far easier, more readable and more performance than C++ streams. You don't need to do any rounding or trimming yourself. Sprintf has flags for that. You probably want something like

与C ++流相比,sprintf将更容易,更易读,性能更高。您不需要自己进行任何舍入或修剪。 Sprintf有旗帜。你可能想要这样的东西

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

Sprintf does the rounding in Java, and I'm pretty sure it will in C++ as well.

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

EDIT:

Sorry, the example code I wrote is for your example. For your original question, change the %.2g to %.6g

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

EDIT:

Changed f to g to suppress trailing zeroes.

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

#3


Have you considered using plain old sprintf to do the formatting?

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

It won't do exactly what you need, but if you round to one hundredths, and then sprintf the number as %f (for float) or %lf (for double float).

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

To round to 100'ths, you could do
num = num + ((int)(num-((int)num))*100)/100;

要舍入到100',你可以做num = num +((int)(num - ((int)num))* 100)/ 100;

#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;
}

#2


sprintf is going to be far easier, more readable and more performance than C++ streams. You don't need to do any rounding or trimming yourself. Sprintf has flags for that. You probably want something like

与C ++流相比,sprintf将更容易,更易读,性能更高。您不需要自己进行任何舍入或修剪。 Sprintf有旗帜。你可能想要这样的东西

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

Sprintf does the rounding in Java, and I'm pretty sure it will in C++ as well.

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

EDIT:

Sorry, the example code I wrote is for your example. For your original question, change the %.2g to %.6g

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

EDIT:

Changed f to g to suppress trailing zeroes.

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

#3


Have you considered using plain old sprintf to do the formatting?

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

It won't do exactly what you need, but if you round to one hundredths, and then sprintf the number as %f (for float) or %lf (for double float).

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

To round to 100'ths, you could do
num = num + ((int)(num-((int)num))*100)/100;

要舍入到100',你可以做num = num +((int)(num - ((int)num))* 100)/ 100;