问题
I'm using the following method to format a number with commas:
template<class T>
static std::string FormatNumberWithCommas(T value, int numberOfDecimalPlaces = 0)
{
std::stringstream ss;
ss.imbue(std::locale(""));
ss.precision(numberOfDecimalPlaces);
ss << std::fixed << value;
return ss.str();
}
Profiling has show this method to take a significant amount of time relative to other code. Specifically the profiler has identified the line:
ss.imbue(std::locale(""));
And within that I believe it is the std::locale("")
that is taking long. How can I improve the performance of this method? If it requires using something other than stringstream or doing something semi-hacky in this particular method I'm open to it.
回答1:
You could start by making the string stream a static variable:
{
static std::stringstream ss;
static bool ss_init = false;
static std::string emtpy_string;
if (!ss_init) { ss.imbue(std::locale("")); ss_init = true; }
ss.str(empty_string);
// ...
}
If that's still a bottleneck, you could look at an alternative formatting library like fastformat.
回答2:
1 using namespace std;
2 template <typename T>
3 string AddCommas(T data);
4 template <>
5 string AddCommas<int>(int data)
6 {
7 stringstream ss; ss << data; string s = ss.str();
8 if (s.length() > 3)
9 for (int i = s.length()-3; i > 0; i -= 3)
10 s.insert(i,",");
11 return s;
12 }
You can use the same code for long. Double is a little trickier.
13 template <>
14 string AddCommas<double>(double data)
15 {
16 stringstream ss; ss << fixed << data; string s = ss.str();
17 string intPart, decPart = "";
18 int pos = s.find('.');
19 if (pos != string::npos) {
20 intPart = s.substr(0,pos);
21 decPart = s.substr(pos,pos-s.length());
22 //remove trailing zeros
23 for (int i = decPart.length()-1; i > 0; i--) {
24 if (decPart[i] == '0') decPart.erase(i);
25 else break;
26 }
27 // remove decimal point if no decimals
28 if (decPart.length() == 1) decPart = "";
29 }
30 else intPart = s;
31 //insert commas
32 if (intPart.length() > 3) {
33 for (int i = intPart.length()-3; i > 0; i -= 3) intPart.insert(i,",");
34 }
35 s = intPart + decPart;
36 return s;
37 }
You can make one for float. The only problem arises if you want to set precision. Then you have to just make a stand alone function and add a parameter for precision. Also you would need to change some of the code:
ss << fixed << setprecision(precision) << data; //...
As well as remove lines 22 through 28.
来源:https://stackoverflow.com/questions/7693751/how-can-i-improve-formatting-number-with-commas-performance