Как я могу улучшить форматирование числа с запятыми? - PullRequest
4 голосов
/ 08 октября 2011

Я использую следующий метод для форматирования числа с запятыми:

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

Профилирование показало, что этот метод занимает значительное время по сравнению с другим кодом.В частности, профилировщик определил строку:

ss.imbue(std::locale(""));

И в этом я полагаю, что std::locale("") занимает много времени.Как я могу улучшить производительность этого метода?Если для этого нужно использовать что-то отличное от stringstream или что-то наполовину хакерское, то я открыт для этого.

Ответы [ 2 ]

4 голосов
/ 08 октября 2011

Вы можете начать с преобразования строки в статическую переменную:

{
  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);
  // ...
}

Если это все еще узкое место, вы можете посмотреть альтернативную библиотеку форматирования, например fastformat .

2 голосов
/ 10 декабря 2012
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 }

Вы можете долго использовать один и тот же код.Double немного сложнее.

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 }

Вы можете сделать один для поплавка.Единственная проблема возникает, если вы хотите установить точность.Затем вам нужно просто создать отдельную функцию и добавить параметр для точности.Также вам необходимо изменить код:

ss << fixed << setprecision(precision) << data; //...

, а также удалить строки с 22 по 28.

...